summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJosh Suereth <Joshua.Suereth@gmail.com>2012-10-11 12:59:27 -0700
committerJosh Suereth <Joshua.Suereth@gmail.com>2012-10-11 12:59:27 -0700
commit25ad7876a97aafb7a33283843b05023e48cedc55 (patch)
treec245a82aa02bbf450ec7151202fd1d9f2fe83d0f
parentca6b863d61dbe8a5838b7e1eff60ab43eed03864 (diff)
parent47f6d964a013db0861c6effd8c8ea7c7a78bd11d (diff)
downloadscala-25ad7876a97aafb7a33283843b05023e48cedc55.tar.gz
scala-25ad7876a97aafb7a33283843b05023e48cedc55.tar.bz2
scala-25ad7876a97aafb7a33283843b05023e48cedc55.zip
Merge pull request #1492 from scalamacros/pullrequest/reflection-docsv2.10.0-RC1
Pullrequest/reflection docs
-rw-r--r--src/compiler/scala/reflect/macros/runtime/Typers.scala3
-rw-r--r--src/library/scala/reflect/ClassTag.scala35
-rw-r--r--src/reflect/scala/reflect/api/Annotations.scala123
-rw-r--r--src/reflect/scala/reflect/api/BuildUtils.scala3
-rw-r--r--src/reflect/scala/reflect/api/Constants.scala187
-rw-r--r--src/reflect/scala/reflect/api/Exprs.scala47
-rw-r--r--src/reflect/scala/reflect/api/FlagSets.scala71
-rw-r--r--src/reflect/scala/reflect/api/Importers.scala76
-rw-r--r--src/reflect/scala/reflect/api/JavaMirrors.scala36
-rw-r--r--src/reflect/scala/reflect/api/JavaUniverse.scala12
-rw-r--r--src/reflect/scala/reflect/api/Mirror.scala40
-rw-r--r--src/reflect/scala/reflect/api/Mirrors.scala251
-rw-r--r--src/reflect/scala/reflect/api/Names.scala70
-rw-r--r--src/reflect/scala/reflect/api/Position.scala111
-rw-r--r--src/reflect/scala/reflect/api/Positions.scala20
-rw-r--r--src/reflect/scala/reflect/api/Printers.scala150
-rw-r--r--src/reflect/scala/reflect/api/Scopes.scala39
-rw-r--r--src/reflect/scala/reflect/api/StandardDefinitions.scala245
-rw-r--r--src/reflect/scala/reflect/api/StandardNames.scala66
-rw-r--r--src/reflect/scala/reflect/api/Symbols.scala412
-rw-r--r--src/reflect/scala/reflect/api/TagInterop.scala23
-rw-r--r--src/reflect/scala/reflect/api/TreeCreator.scala20
-rw-r--r--src/reflect/scala/reflect/api/Trees.scala1378
-rw-r--r--src/reflect/scala/reflect/api/TypeCreator.scala18
-rw-r--r--src/reflect/scala/reflect/api/TypeTags.scala277
-rw-r--r--src/reflect/scala/reflect/api/Types.scala350
-rw-r--r--src/reflect/scala/reflect/api/Universe.scala105
-rw-r--r--src/reflect/scala/reflect/api/package.scala95
-rw-r--r--src/reflect/scala/reflect/internal/util/Position.scala44
-rw-r--r--src/reflect/scala/reflect/macros/Aliases.scala76
-rw-r--r--src/reflect/scala/reflect/macros/Context.scala65
-rw-r--r--src/reflect/scala/reflect/macros/Enclosures.scala5
-rw-r--r--src/reflect/scala/reflect/macros/Evals.scala47
-rw-r--r--src/reflect/scala/reflect/macros/ExprUtils.scala16
-rw-r--r--src/reflect/scala/reflect/macros/FrontEnds.scala28
-rw-r--r--src/reflect/scala/reflect/macros/Infrastructure.scala3
-rw-r--r--src/reflect/scala/reflect/macros/Names.scala11
-rw-r--r--src/reflect/scala/reflect/macros/Parsers.scala12
-rw-r--r--src/reflect/scala/reflect/macros/Reifiers.scala3
-rw-r--r--src/reflect/scala/reflect/macros/TreeBuilder.scala17
-rw-r--r--src/reflect/scala/reflect/macros/Typers.scala3
-rw-r--r--src/reflect/scala/reflect/macros/Universe.scala106
-rw-r--r--src/reflect/scala/reflect/macros/package.scala8
-rw-r--r--src/reflect/scala/reflect/runtime/JavaUniverse.scala7
-rw-r--r--src/reflect/scala/reflect/runtime/package.scala15
45 files changed, 3943 insertions, 786 deletions
diff --git a/src/compiler/scala/reflect/macros/runtime/Typers.scala b/src/compiler/scala/reflect/macros/runtime/Typers.scala
index be70181126..f9add91b9a 100644
--- a/src/compiler/scala/reflect/macros/runtime/Typers.scala
+++ b/src/compiler/scala/reflect/macros/runtime/Typers.scala
@@ -8,6 +8,9 @@ trait Typers {
def openImplicits: List[(Type, Tree)] = callsiteTyper.context.openImplicits
+ /**
+ * @see [[scala.tools.reflect.Toolbox.typeCheck]]
+ */
def typeCheck(tree: Tree, pt: Type = universe.WildcardType, silent: Boolean = false, withImplicitViewsDisabled: Boolean = false, withMacrosDisabled: Boolean = false): Tree = {
macroLogVerbose("typechecking %s with expected type %s, implicit views = %s, macros = %s".format(tree, pt, !withImplicitViewsDisabled, !withMacrosDisabled))
val context = callsiteTyper.context
diff --git a/src/library/scala/reflect/ClassTag.scala b/src/library/scala/reflect/ClassTag.scala
index 5c2067a548..d699e34ffc 100644
--- a/src/library/scala/reflect/ClassTag.scala
+++ b/src/library/scala/reflect/ClassTag.scala
@@ -5,19 +5,34 @@ import java.lang.{ Class => jClass }
import scala.language.{implicitConversions, existentials}
import scala.runtime.ScalaRunTime.{ arrayClass, arrayElementClass }
-/** A `ClassTag[T]` wraps a runtime class (the erasure) and can create array instances.
+/**
+ *
+ * A `ClassTag[T]` stores the erased class of a given type `T`, accessible via the `runtimeClass`
+ * field. This is particularly useful for instantiating `Array`s whose element types are unknown
+ * at compile time.
+ *
+ * `ClassTag`s are a weaker special case of [[scala.reflect.api.TypeTags#TypeTag]]s, in that they
+ * wrap only the runtime class of a given type, whereas a `TypeTag` contains all static type
+ * information. That is, `ClassTag`s are constructed from knowing only the top-level class of a
+ * type, without necessarily knowing all of its argument types. This runtime information is enough
+ * for runtime `Array` creation.
*
- * If an implicit value of type ClassTag[T] is requested, the compiler will create one.
- * The runtime class (i.e. the erasure, a java.lang.Class on the JVM) of T can be accessed
- * via the `runtimeClass` field. References to type parameters or abstract type members are
- * replaced by the concrete types if ClassTags are available for them.
+ * For example:
+ * {{{
+ * scala> def mkArray[T : ClassTag](elems: T*) = Array[T](elems: _*)
+ * mkArray: [T](elems: T*)(implicit evidence$1: scala.reflect.ClassTag[T])Array[T]
*
- * Besides accessing the erasure, a ClassTag knows how to instantiate single- and multi-
- * dimensional `Arrays` where the element type is unknown at compile time.
+ * scala> mkArray(42, 13)
+ * res0: Array[Int] = Array(42, 13)
*
- * [[scala.reflect.ClassTag]] corresponds to a previous concept of [[scala.reflect.ClassManifest]].
+ * scala> mkArray("Japan","Brazil","Germany")
+ * res1: Array[String] = Array(Japan, Brazil, Germany)
+ * }}}
+ *
+ * See [[scala.reflect.api.TypeTags]] for more examples, or the
+ * [[http://docs.scala-lang.org/overviews/reflection/typetags-manifests.html Reflection Guide: TypeTags]]
+ * for more details.
*
- * @see [[scala.reflect.api.TypeTags]]
*/
@scala.annotation.implicitNotFound(msg = "No ClassTag available for ${T}")
trait ClassTag[T] extends ClassManifestDeprecatedApis[T] with Equals with Serializable {
@@ -29,7 +44,7 @@ trait ClassTag[T] extends ClassManifestDeprecatedApis[T] with Equals with Serial
*/
def runtimeClass: jClass[_]
- /** Produces a `ClassTag` that knows how to build `Array[Array[T]]` */
+ /** Produces a `ClassTag` that knows how to instantiate an `Array[Array[T]]` */
def wrap: ClassTag[Array[T]] = ClassTag[Array[T]](arrayClass(runtimeClass))
/** Produces a new array with element type `T` and length `len` */
diff --git a/src/reflect/scala/reflect/api/Annotations.scala b/src/reflect/scala/reflect/api/Annotations.scala
index 37882a9f3c..fb353a5520 100644
--- a/src/reflect/scala/reflect/api/Annotations.scala
+++ b/src/reflect/scala/reflect/api/Annotations.scala
@@ -3,122 +3,195 @@ package api
import scala.collection.immutable.ListMap
-/**
- * Defines the type hierarchy for annotations.
+/** This trait provides annotation support for the reflection API.
+ *
+ * The API distinguishes between two kinds of annotations:
+ *
+ * <ul>
+ * <li>''Java annotations'': annotations on definitions produced by the Java compiler, i.e., subtypes of [[java.lang.annotation.Annotation]]
+ * attached to program definitions. When read by Scala reflection, the [[scala.annotation.ClassfileAnnotation]] trait
+ * is automatically added as a subclass to every Java annotation.</li>
+ * <li>''Scala annotations'': annotations on definitions or types produced by the Scala compiler.</li>
+ * </ul>
+ *
+ * When a Scala annotation that inherits from [[scala.annotation.StaticAnnotation]] or [[scala.annotation.ClassfileAnnotation]] is compiled,
+ * it is stored as special attributes in the corresponding classfile, and not as a Java annotation. Note that subclassing
+ * just [[scala.annotation.Annotation]] is not enough to have the corresponding metadata persisted for runtime reflection.
+ *
+ * The distinction between Java and Scala annotations is manifested in the contract of [[scala.reflect.api.Annotations#Annotation]], which exposes
+ * both `scalaArgs` and `javaArgs`. For Scala or Java annotations extending [[scala.annotation.ClassfileAnnotation]] `scalaArgs` is empty
+ * and arguments are stored in `javaArgs`. For all other Scala annotations, arguments are stored in `scalaArgs` and `javaArgs` is empty.
+ *
+ * Arguments in `scalaArgs` are represented as typed trees. Note that these trees are not transformed by any phases
+ * following the type-checker. Arguments in `javaArgs` are repesented as a map from [[scala.reflect.api.Names#Name]] to
+ * [[scala.reflect.api.Annotations#JavaArgument]]. Instances of `JavaArgument` represent different kinds of Java annotation arguments:
+ * - literals (primitive and string constants),
+ * - arrays and
+ * - nested annotations.
+ *
+ * @contentDiagram hideNodes "*Api"
*/
trait Annotations { self: Universe =>
- /** Typed information about an annotation. It can be attached to either a symbol or an annotated type.
- *
- * Annotations are either ''Scala annotations'', which conform to [[scala.annotation.StaticAnnotation]]
- * or ''Java annotations'', which conform to [[scala.annotation.ClassfileAnnotation]].
- * Trait `ClassfileAnnotation` is automatically added to every Java annotation by the scalac classfile parser.
+ /** Information about an annotation.
+ * @template
+ * @group Annotations
*/
type Annotation >: Null <: AnyRef with AnnotationApi
/** A tag that preserves the identity of the `Annotation` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val AnnotationTag: ClassTag[Annotation]
- /** The constructor/deconstructor for `Annotation` instances. */
+ /** The constructor/deconstructor for `Annotation` instances.
+ * @group Extractors
+ */
val Annotation: AnnotationExtractor
- /** An extractor class to create and pattern match with syntax `Annotation(atp, scalaArgs, javaArgs)`.
- * Here, `atp` is the annotation type, `scalaArgs` the arguments, and `javaArgs` the annotation's key-value
- * pairs.
- *
- * Annotations are pickled, i.e. written to scala symtab attribute in the classfile.
- * Annotations are written to the classfile as Java annotations if `atp` conforms to `ClassfileAnnotation`.
- *
- * For Scala annotations, arguments are stored in `scalaArgs` and `javaArgs` is empty. Arguments in
- * `scalaArgs` are represented as typed trees. Note that these trees are not transformed by any phases
- * following the type-checker. For Java annotations, `scalaArgs` is empty and arguments are stored in
- * `javaArgs`.
- */
+ /** An extractor class to create and pattern match with syntax `Annotation(tpe, scalaArgs, javaArgs)`.
+ * Here, `tpe` is the annotation type, `scalaArgs` the payload of Scala annotations, and `javaArgs` the payload of Java annotations.
+ * @group Extractors
+ */
abstract class AnnotationExtractor {
def apply(tpe: Type, scalaArgs: List[Tree], javaArgs: ListMap[Name, JavaArgument]): Annotation
def unapply(ann: Annotation): Option[(Type, List[Tree], ListMap[Name, JavaArgument])]
}
+ /** The API of `Annotation` instances.
+ * The main source of information about annotations is the [[scala.reflect.api.Annotations]] page.
+ * @group API
+ */
trait AnnotationApi {
+ /** The type of the annotation. */
def tpe: Type
+
+ /** Payload of the Scala annotation: a list of abstract syntax trees that represent the argument.
+ * Empty for Java annotations.
+ */
def scalaArgs: List[Tree]
+
+ /** Payload of the Java annotation: a list of name-value pairs.
+ * Empty for Scala annotations.
+ */
def javaArgs: ListMap[Name, JavaArgument]
}
- /** A Java annotation argument */
+ /** A Java annotation argument
+ * @template
+ * @group Annotations
+ */
type JavaArgument >: Null <: AnyRef
+
+ /** A tag that preserves the identity of the `JavaArgument` abstract type from erasure.
+ * Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
+ */
implicit val JavaArgumentTag: ClassTag[JavaArgument]
- /** A literal argument to a Java annotation as `"Use X instead"` in `@Deprecated("Use X instead")`*/
+ /** A literal argument to a Java annotation as `"Use X instead"` in `@Deprecated("Use X instead")`
+ * @template
+ * @group Annotations
+ */
type LiteralArgument >: Null <: AnyRef with JavaArgument with LiteralArgumentApi
/** A tag that preserves the identity of the `LiteralArgument` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val LiteralArgumentTag: ClassTag[LiteralArgument]
- /** The constructor/deconstructor for `LiteralArgument` instances. */
+ /** The constructor/deconstructor for `LiteralArgument` instances.
+ * @group Extractors
+ */
val LiteralArgument: LiteralArgumentExtractor
/** An extractor class to create and pattern match with syntax `LiteralArgument(value)`
* where `value` is the constant argument.
+ * @group Extractors
*/
abstract class LiteralArgumentExtractor {
def apply(value: Constant): LiteralArgument
def unapply(arg: LiteralArgument): Option[Constant]
}
+ /** The API of `LiteralArgument` instances.
+ * The main source of information about annotations is the [[scala.reflect.api.Annotations]] page.
+ * @group API
+ */
trait LiteralArgumentApi {
+ /** The underlying compile-time constant value. */
def value: Constant
}
/** An array argument to a Java annotation as in `@Target(value={TYPE,FIELD,METHOD,PARAMETER})`
+ * @template
+ * @group Annotations
*/
type ArrayArgument >: Null <: AnyRef with JavaArgument with ArrayArgumentApi
/** A tag that preserves the identity of the `ArrayArgument` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val ArrayArgumentTag: ClassTag[ArrayArgument]
- /** The constructor/deconstructor for `ArrayArgument` instances. */
+ /** The constructor/deconstructor for `ArrayArgument` instances.
+ * @group Extractors
+ */
val ArrayArgument: ArrayArgumentExtractor
/** An extractor class to create and pattern match with syntax `ArrayArgument(args)`
* where `args` is the argument array.
+ * @group Extractors
*/
abstract class ArrayArgumentExtractor {
def apply(args: Array[JavaArgument]): ArrayArgument
def unapply(arg: ArrayArgument): Option[Array[JavaArgument]]
}
+ /** API of `ArrayArgument` instances.
+ * The main source of information about annotations is the [[scala.reflect.api.Annotations]] page.
+ * @group API
+ */
trait ArrayArgumentApi {
+ /** The underlying array of Java annotation arguments. */
def args: Array[JavaArgument]
}
/** A nested annotation argument to a Java annotation as `@Nested` in `@Outer(@Nested)`.
+ * @template
+ * @group Annotations
*/
type NestedArgument >: Null <: AnyRef with JavaArgument with NestedArgumentApi
/** A tag that preserves the identity of the `NestedArgument` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val NestedArgumentTag: ClassTag[NestedArgument]
- /** The constructor/deconstructor for `NestedArgument` instances. */
+ /** The constructor/deconstructor for `NestedArgument` instances.
+ * @group Extractors
+ */
val NestedArgument: NestedArgumentExtractor
/** An extractor class to create and pattern match with syntax `NestedArgument(annotation)`
* where `annotation` is the nested annotation.
+ * @group Extractors
*/
abstract class NestedArgumentExtractor {
def apply(annotation: Annotation): NestedArgument
def unapply(arg: NestedArgument): Option[Annotation]
}
+ /** API of `NestedArgument` instances.
+ * The main source of information about annotations is the [[scala.reflect.api.Annotations]] page.
+ * @group API
+ */
trait NestedArgumentApi {
+ /** The underlying nested annotation. */
def annotation: Annotation
}
} \ No newline at end of file
diff --git a/src/reflect/scala/reflect/api/BuildUtils.scala b/src/reflect/scala/reflect/api/BuildUtils.scala
index b0de7f8d5a..0c8e81a220 100644
--- a/src/reflect/scala/reflect/api/BuildUtils.scala
+++ b/src/reflect/scala/reflect/api/BuildUtils.scala
@@ -3,15 +3,18 @@ package api
/**
* This is an internal implementation class.
+ * @groupname TreeBuilders Tree Building
*/
private[reflect] trait BuildUtils { self: Universe =>
+ /** @group TreeBuilders */
val build: BuildApi
// this API abstracts away the functionality necessary for reification
// it's too gimmicky and unstructured to be exposed directly in the universe
// but we need it in a publicly available place for reification to work
+ /** @group TreeBuilders */
abstract class BuildApi {
/** Selects type symbol with given simple name `name` from the defined members of `owner`.
*/
diff --git a/src/reflect/scala/reflect/api/Constants.scala b/src/reflect/scala/reflect/api/Constants.scala
index 2f201d033d..a92fc5cbb3 100644
--- a/src/reflect/scala/reflect/api/Constants.scala
+++ b/src/reflect/scala/reflect/api/Constants.scala
@@ -7,35 +7,214 @@ package scala.reflect
package api
/**
- * Defines the type hierachy for compile-time constants.
+ * 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.
*
- * @see [[scala.reflect]] for a description on how the class hierarchy is encoded here.
+ * [[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
+ * }
+ * }}}
+ *
+ * @contentDiagram hideNodes "*Api"
*/
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.
+ * @group API
+ */
abstract class ConstantApi {
+ /** Payload of the constant, that can be accessed directly or pattern matched against. */
val value: Any
+
+ /** Scala type that describes the constant. It is generated automatically based on the type of the value. */
def tpe: Type
}
}
diff --git a/src/reflect/scala/reflect/api/Exprs.scala b/src/reflect/scala/reflect/api/Exprs.scala
index b86f36420d..45bfddb55d 100644
--- a/src/reflect/scala/reflect/api/Exprs.scala
+++ b/src/reflect/scala/reflect/api/Exprs.scala
@@ -8,9 +8,29 @@ package api
import scala.reflect.runtime.{universe => ru}
+/** A trait that defines strongly-typed tree wrappers and operations on them for use in Scala Reflection.
+ *
+ * `Expr` wraps an abstract syntax tree ([[scala.reflect.api.Trees#Tree]]) and tags it with its type ([[scala.reflect.api.Types#Type]]).
+ *
+ * Usually `Expr`s are created via [[scala.reflect.api.Universe#reify]], in which case a compiler
+ * produces a [[scala.reflect.api.TreeCreator]] for the provided expression and also
+ * creates a complementary [[scala.reflect.api.TypeTags#WeakTypeTag]] that corresponds to the type of that expression.
+ *
+ * `Expr`s can also be created manually via the `Expr` companion object, but then the burden of providing a `TreeCreator` lies on the programmer.
+ * Compile-time reflection via macros, as described in [[scala.reflect.macros.Aliases]], provides an easier way to instantiate exprs manually.
+ * Manual creation, however, is very rarely needed when working with runtime reflection.
+ *
+ * `Expr` can be migrated from one mirror to another by using the `in` method. Migration means that all symbolic references
+ * to classes/objects/packages in the expression are re-resolved within the new mirror
+ * (typically using that mirror's classloader). The default universe of an `Expr` is typically
+ * [[scala.reflect.runtime#universe]], the default mirror is typically [[scala.reflect.runtime#currentMirror]].
+ */
trait Exprs { self: Universe =>
- /** Expr wraps an expression tree and tags it with its type. */
+ /** Expr wraps an abstract syntax tree and tags it with its type.
+ * The main source of information about exprs is the [[scala.reflect.api.Exprs]] page.
+ * @group Expressions
+ */
trait Expr[+T] extends Equals with Serializable {
/**
* Underlying mirror of this expr.
@@ -19,23 +39,24 @@ trait Exprs { self: Universe =>
/**
* Migrates the expression into another mirror, jumping into a different universe if necessary.
- *
- * This means that all symbolic references to classes/objects/packages in the expression
- * will be re-resolved within the new mirror (typically using that mirror's classloader).
*/
def in[U <: Universe with Singleton](otherMirror: scala.reflect.api.Mirror[U]): U # Expr[T]
/**
- * The Scala syntax tree representing the wrapped expression.
+ * The Scala abstract syntax tree representing the wrapped expression.
*/
def tree: Tree
/**
- * Representation of the type of the wrapped expression tree as found via type tags.
+ * Type of the wrapped expression tree as provided during creation.
+ *
+ * When exprs are created by the compiler, `staticType` represents
+ * a statically known type of the tree as calculated at that point by the compiler.
*/
def staticType: Type
+
/**
- * Representation of the type of the wrapped expression tree as found in the tree.
+ * Type of the wrapped expression tree as found in the underlying tree.
*/
def actualType: Type
@@ -65,6 +86,7 @@ trait Exprs { self: Universe =>
* because expr of type Expr[T] itself does not have a method foo.
*/
def splice: T
+
/**
* A dummy value to denote cross-stage path-dependent type dependencies.
*
@@ -81,10 +103,16 @@ trait Exprs { self: Universe =>
*/
val value: T
- /** case class accessories */
+ /** TODO how do I doc this? */
override def canEqual(x: Any) = x.isInstanceOf[Expr[_]]
+
+ /** TODO how do I doc this? */
override def equals(x: Any) = x.isInstanceOf[Expr[_]] && this.mirror == x.asInstanceOf[Expr[_]].mirror && this.tree == x.asInstanceOf[Expr[_]].tree
+
+ /** TODO how do I doc this? */
override def hashCode = mirror.hashCode * 31 + tree.hashCode
+
+ /** TODO how do I doc this? */
override def toString = "Expr["+staticType+"]("+tree+")"
}
@@ -93,6 +121,9 @@ trait Exprs { self: Universe =>
*
* Can be useful, when having a tree and wanting to splice it in reify call,
* in which case the tree first needs to be wrapped in an expr.
+
+ * The main source of information about exprs is the [[scala.reflect.api.Exprs]] page.
+ * @group Expressions
*/
object Expr {
def apply[T: WeakTypeTag](mirror: scala.reflect.api.Mirror[self.type], treec: TreeCreator): Expr[T] = new ExprImpl[T](mirror.asInstanceOf[Mirror], treec)
diff --git a/src/reflect/scala/reflect/api/FlagSets.scala b/src/reflect/scala/reflect/api/FlagSets.scala
index 3eda54b28a..a7d1ca05a6 100644
--- a/src/reflect/scala/reflect/api/FlagSets.scala
+++ b/src/reflect/scala/reflect/api/FlagSets.scala
@@ -3,22 +3,83 @@ package api
import scala.language.implicitConversions
+/**
+ * The trait that defines flag sets and operations on them.
+ *
+ * `Flag`s are used to provide modifiers for abstract syntax trees that represent definitions
+ * via the `flags` field of [[scala.reflect.api.Trees#Modifiers]]. Trees that accept modifiers are:
+ *
+ * - '''[[scala.reflect.api.Trees#ClassDef]]'''. Classes and traits.
+ * - '''[[scala.reflect.api.Trees#ModuleDef]]'''. Objects.
+ * - '''[[scala.reflect.api.Trees#ValDef]]'''. Vals, vars, parameters and self-type annotations.
+ * - '''[[scala.reflect.api.Trees#DefDef]]'''. Methods and constructors.
+ * - '''[[scala.reflect.api.Trees#TypeDef]]'''. Type aliases, abstract type members and type parameters.
+ *
+ * For example, to create a class named `C` one would write something like:
+ * {{{
+ * ClassDef(Modifiers(NoFlags), newTypeName("C"), Nil, ...)
+ * }}}
+ *
+ * Here, the flag set is empty.
+ *
+ * To make `C` private, one would write something like:
+ * {{{
+ * ClassDef(Modifiers(PRIVATE), newTypeName("C"), Nil, ...)
+ * }}}
+ *
+ * Flags can also be combined with the vertical bar operator (`|`).
+ * For example, a private final class is written something like:
+ * {{{
+ * ClassDef(Modifiers(PRIVATE | FINAL), newTypeName("C"), Nil, ...)
+ * }}}
+ *
+ * The list of all available flags is defined in [[scala.reflect.api.FlagSets#FlagValues]], available via
+ * [[scala.reflect.api.FlagSets#Flag]]. (Typically one writes a blanket import for this, e.g.
+ * `import scala.reflect.runtime.universe.Flag._`).
+ *
+ * Definition trees are compiled down to symbols, so flags on modifiers of these trees are transformed into flags
+ * on the resulting symbols. Unlike trees, symbols don't expose flags, but rather provide `isXXX` test methods
+ * (e.g. `isFinal` can be used to test finality). These test methods might require an upcast with `asTerm`,
+ * `asType` or `asClass` as some flags only make sense for certain kinds of symbols.
+ *
+ * ''Of Note:'' This part of the Reflection API is being considered as a candidate for redesign. It is
+ * quite possible that in future releases of the reflection API, flag sets could be replaced with something else.
+ *
+ * For more details about `FlagSet`s and other aspects of Scala reflection, see the
+ * [[http://docs.scala-lang.org/overviews/reflection/overview.html Reflection Guide]]
+ *
+ */
trait FlagSets { self: Universe =>
- /** An abstract type representing sets of flags (like private, final, etc.) that apply to definition trees and symbols */
+ /** An abstract type representing sets of flags (like private, final, etc.) that apply to definition trees and symbols
+ * @template
+ * @group Flags
+ */
type FlagSet
/** A tag that preserves the identity of the `FlagSet` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val FlagSetTag: ClassTag[FlagSet]
+ /** The API of `FlagSet` instances.
+ * The main source of information about flag sets is the [[scala.reflect.api.FlagSets]] page.
+ * @group Flags
+ */
trait FlagOps extends Any {
+ /** Produces a flag set that's a union of this flag set and the provided flag set. */
def | (right: FlagSet): FlagSet
}
+ /** The API of `FlagSet` instances.
+ * @group Flags
+ */
implicit def addFlagOps(left: FlagSet): FlagOps
+ /** A module that contains all possible values that can constitute flag sets.
+ * @group Flags
+ */
val Flag: FlagValues
// Q: I have a pretty flag. Can I put it here?
@@ -26,6 +87,10 @@ trait FlagSets { self: Universe =>
// If you want to put a flag here so that it can be tested against,
// introduce an `isXXX` method in one of the `api.Symbols` classes instead.
+ /** All possible values that can constitute flag sets.
+ * The main source of information about flag sets is the [[scala.reflect.api.FlagSets]] page.
+ * @group Flags
+ */
trait FlagValues {
/** Flag indicating that tree represents a trait */
@@ -104,6 +169,8 @@ trait FlagSets { self: Universe =>
val DEFAULTINIT: FlagSet
}
- /** The empty set of flags */
+ /** The empty set of flags
+ * @group Flags
+ */
val NoFlags: FlagSet
}
diff --git a/src/reflect/scala/reflect/api/Importers.scala b/src/reflect/scala/reflect/api/Importers.scala
index fbc29a514e..4286b2b45c 100644
--- a/src/reflect/scala/reflect/api/Importers.scala
+++ b/src/reflect/scala/reflect/api/Importers.scala
@@ -1,21 +1,97 @@
package scala.reflect
package api
+/** This trait provides support for importers, a facility to migrate reflection artifacts between universes.
+ *
+ * Reflection artifacts, such as [[scala.reflect.api.Symbols Symbols]] and [[scala.reflect.api.Types Types]],
+ * are contained in [[scala.reflect.api.Universes Universe]]s. Typically all processing happens
+ * within a single `Universe` (e.g. a compile-time macro `Universe` or a runtime reflection `Universe`), but sometimes
+ * there is a need to migrate artifacts from one `Universe` to another. For example, runtime compilation works by
+ * importing runtime reflection trees into a runtime compiler universe, compiling the importees and exporting the
+ * result back.
+ *
+ * Reflection artifacts are firmly grounded in their `Universe`s, which is reflected by the fact that types of artifacts
+ * from different universes are not compatible. By using `Importer`s, however, they be imported from one universe
+ * into another. For example, to import `foo.bar.Baz` from the source `Universe` to the target `Universe`,
+ * an importer will first check whether the entire owner chain exists in the target `Universe`.
+ * If it does, then nothing else will be done. Otherwise, the importer will recreate the entire owner chain
+ * and will import the corresponding type signatures into the target `Universe`.
+ *
+ * Since importers match `Symbol` tables of the source and the target `Universe`s using plain string names,
+ * it is programmer's responsibility to make sure that imports don't distort semantics, e.g., that
+ * `foo.bar.Baz` in the source `Universe` means the same that `foo.bar.Baz` does in the target `Universe`.
+ *
+ * === Example ===
+ *
+ * Here's how one might implement a macro that performs compile-time evaluation of its argument
+ * by using a runtime compiler to compile and evaluate a tree that belongs to a compile-time compiler:
+ *
+ * {{{
+ * def staticEval[T](x: T) = macro staticEval[T]
+ *
+ * def staticEval[T](c: scala.reflect.macros.Context)(x: c.Expr[T]) = {
+ * // creates a runtime reflection universe to host runtime compilation
+ * import scala.reflect.runtime.{universe => ru}
+ * val mirror = ru.runtimeMirror(c.libraryClassLoader)
+ * import scala.tools.reflect.ToolBox
+ * val toolBox = mirror.mkToolBox()
+ *
+ * // runtime reflection universe and compile-time macro universe are different
+ * // therefore an importer is needed to bridge them
+ * // currently mkImporter requires a cast to correctly assign the path-dependent types
+ * val importer0 = ru.mkImporter(c.universe)
+ * val importer = importer0.asInstanceOf[ru.Importer { val from: c.universe.type }]
+ *
+ * // the created importer is used to turn a compiler tree into a runtime compiler tree
+ * // both compilers use the same classpath, so semantics remains intact
+ * val imported = importer.importTree(tree)
+ *
+ * // after the tree is imported, it can be evaluated as usual
+ * val tree = toolBox.resetAllAttrs(imported.duplicate)
+ * val valueOfX = toolBox.eval(imported).asInstanceOf[T]
+ * ...
+ * }
+ * }}}
+ */
trait Importers { self: Universe =>
+ /** Creates an importer that moves reflection artifacts between universes.
+ * @group Importers
+ */
def mkImporter(from0: Universe): Importer { val from: from0.type }
+ /** The API of importers.
+ * The main source of information about importers is the [[scala.reflect.api.Importers]] page.
+ * @group Importers
+ */
trait Importer {
+ /** The source universe of reflection artifacts that will be processed.
+ * The target universe is universe that created this importer with `mkImporter`.
+ */
val from: Universe
+ /** An importer that works in reverse direction, namely:
+ * imports reflection artifacts from the current universe to the universe specified in `from`.
+ */
val reverse: from.Importer { val from: self.type }
+ /** In the current universe, locates or creates a symbol that corresponds to the provided symbol in the source universe.
+ * If necessary imports the owner chain, companions, type signature, annotations and attachments.
+ */
def importSymbol(sym: from.Symbol): Symbol
+ /** In the current universe, locates or creates a type that corresponds to the provided type in the source universe.
+ * If necessary imports the underlying symbols, annotations, scopes and trees.
+ */
def importType(tpe: from.Type): Type
+ /** In the current universe, creates a tree that corresponds to the provided tree in the source universe.
+ * If necessary imports the underlying symbols, types and attachments.
+ */
def importTree(tree: from.Tree): Tree
+ /** In the current universe, creates a position that corresponds to the provided position in the source universe.
+ */
def importPosition(pos: from.Position): Position
}
} \ No newline at end of file
diff --git a/src/reflect/scala/reflect/api/JavaMirrors.scala b/src/reflect/scala/reflect/api/JavaMirrors.scala
index cb0fa0f650..df099006b5 100644
--- a/src/reflect/scala/reflect/api/JavaMirrors.scala
+++ b/src/reflect/scala/reflect/api/JavaMirrors.scala
@@ -1,16 +1,52 @@
package scala.reflect
package api
+/** A refinement of [[scala.reflect.api.Mirror]] for runtime reflection using JVM classloaders.
+ *
+ * This refinement equips mirrors with reflection capabilities for the JVM. `JavaMirror` can
+ * convert Scala reflection artifacts (symbols and types) into Java reflection artifacts (classes)
+ * and vice versa. It can also perform reflective invocations (getting/setting field values,
+ * calling methods, etc).
+ *
+ * For more information about `Mirrors`s, see [[scala.reflect.api.Mirrors]] or the
+ * [[http://docs.scala-lang.org/overviews/reflection/environment-universes-mirrors.html Reflection Guide: Mirrors]]
+ *
+ * @groupname JavaMirrors Java Mirrors
+ */
trait JavaMirrors { self: JavaUniverse =>
+ /** In runtime reflection universes, runtime representation of a class is `java.lang.Class`.
+ * @group JavaMirrors
+ */
type RuntimeClass = java.lang.Class[_]
+ /** In runtime reflection universes, mirrors are `JavaMirrors`.
+ * @group JavaMirrors
+ */
override type Mirror >: Null <: JavaMirror
+ /** A refinement of [[scala.reflect.api.Mirror]] for runtime reflection using JVM classloaders.
+ *
+ * With this upgrade, mirrors become capable of converting Scala reflection artifacts (symbols and types)
+ * into Java reflection artifacts (classes) and vice versa. Consequently, refined mirrors
+ * become capable of performing reflective invocations (getting/setting field values, calling methods, etc).
+ *
+ * For more information about `Mirrors`s, see [[scala.reflect.api.Mirrors]] or the
+ * [[http://docs.scala-lang.org/overviews/reflection/environment-universes-mirrors.html Reflection Guide: Mirrors]]
+ *
+ * @group JavaMirrors
+ */
trait JavaMirror extends scala.reflect.api.Mirror[self.type] with RuntimeMirror {
val classLoader: ClassLoader
override def toString = s"JavaMirror with ${runtime.ReflectionUtils.show(classLoader)}"
}
+ /** Creates a runtime reflection mirror from a JVM classloader.
+ *
+ * For more information about `Mirrors`s, see [[scala.reflect.api.Mirrors]] or the
+ * [[http://docs.scala-lang.org/overviews/reflection/environment-universes-mirrors.html Reflection Guide: Mirrors]]
+ *
+ * @group JavaMirrors
+ */
def runtimeMirror(cl: ClassLoader): Mirror
}
diff --git a/src/reflect/scala/reflect/api/JavaUniverse.scala b/src/reflect/scala/reflect/api/JavaUniverse.scala
index 1a8a02776b..f83692034f 100644
--- a/src/reflect/scala/reflect/api/JavaUniverse.scala
+++ b/src/reflect/scala/reflect/api/JavaUniverse.scala
@@ -1,8 +1,19 @@
package scala.reflect
package api
+/** A refinement of [[scala.reflect.api.Universe]] for runtime reflection using JVM classloaders.
+ *
+ * The refinement consists of an upgrade to the mirror API, which gets extended from [[scala.reflect.api.Mirror]]
+ * to [[scala.reflect.api.JavaMirrors#JavaMirror]].
+ *
+ * See the [[http://docs.scala-lang.org/overviews/reflection/overview.html Reflection Guide]] for details on how to use runtime reflection.
+ * @groupname JavaUniverse Java Mirrors
+ *
+ * @contentDiagram hideNodes "*Api"
+ */
trait JavaUniverse extends Universe with JavaMirrors { self =>
+ /* @group JavaUniverse */
override def typeTagToManifest[T: ClassTag](mirror0: Any, tag: Universe # TypeTag[T]): Manifest[T] = {
// SI-6239: make this conversion more precise
val mirror = mirror0.asInstanceOf[Mirror]
@@ -10,6 +21,7 @@ trait JavaUniverse extends Universe with JavaMirrors { self =>
Manifest.classType(runtimeClass).asInstanceOf[Manifest[T]]
}
+ /* @group JavaUniverse */
override def manifestToTypeTag[T](mirror0: Any, manifest: Manifest[T]): Universe # TypeTag[T] =
TypeTag(mirror0.asInstanceOf[Mirror], new TypeCreator {
def apply[U <: Universe with Singleton](mirror: scala.reflect.api.Mirror[U]): U # Type = {
diff --git a/src/reflect/scala/reflect/api/Mirror.scala b/src/reflect/scala/reflect/api/Mirror.scala
index 2de0d7120e..b1290cc02e 100644
--- a/src/reflect/scala/reflect/api/Mirror.scala
+++ b/src/reflect/scala/reflect/api/Mirror.scala
@@ -2,32 +2,41 @@ package scala.reflect
package api
/**
- * The base interface for all mirrors.
+ * The base class for all mirrors.
*
- * @tparam U the type of the universe this mirror belongs to.
- *
- * This is defined outside the reflection universe cake pattern implementation
- * so that it can be referenced from outside. For example TypeCreator and TreeCreator
- * reference Mirror and also need to be defined outside the cake as they are
- * used by type tags, which can be migrated between different universes and consequently
- * cannot be bound to a fixed one.
+ * See [[scala.reflect.api.Mirrors]] or [[docs.scala-lang.org/overviews/reflection/overview.html Reflection Guide]]
+ * for a complete overview of `Mirror`s.
*
- * @see [[Mirrors]]
+ * @tparam U the type of the universe this mirror belongs to.
*/
+// Note: Unlike most Scala reflection artifact classes, `Mirror` is not defined as an inner class,
+// so that it can be referenced from outside. For example, [[scala.reflect.api.TypeCreator]] and [[scala.reflect.api.TreeCreator]]
+// reference `Mirror` and also need to be defined outside the cake as they are used by type tags, which can be migrated between
+// different universes and consequently cannot be bound to a fixed one.
abstract class Mirror[U <: Universe with Singleton] {
- /** The universe this mirror belongs to. */
+ /** The universe this mirror belongs to.
+ * @group Mirror
+ */
val universe: U
- /** The class symbol of the `_root_` package */
+ /** The class symbol of the `_root_` package
+ * @group Mirror
+ */
def RootClass: U#ClassSymbol
- /** The module symbol of the `_root_` package */
+ /** The module symbol of the `_root_` package
+ * @group Mirror
+ */
def RootPackage: U#ModuleSymbol
- /** The module class symbol of the default (unnamed) package */
+ /** The module class symbol of the default (unnamed) package
+ * @group Mirror
+ */
def EmptyPackageClass: U#ClassSymbol
- /** The module symbol of the default (unnamed) package */
+ /** The module symbol of the default (unnamed) package
+ * @group Mirror
+ */
def EmptyPackage: U#ModuleSymbol
/** The symbol corresponding to the globally accessible class with the
@@ -71,6 +80,7 @@ abstract class Mirror[U <: Universe with Singleton] {
*
* In the example above, to load a symbol that corresponds to the class B declared in the object foo,
* use staticModule("foo") to load the module symbol and then navigate typeSignature.members of its moduleClass.
+ * @group Mirror
*/
def staticClass(fullName: String): U#ClassSymbol
@@ -97,11 +107,13 @@ abstract class Mirror[U <: Universe with Singleton] {
*
* In the example above, to load a symbol that corresponds to the object B declared in the object foo,
* use staticModule("foo") to load the module symbol and then navigate typeSignature.members of its moduleClass.
+ * @group Mirror
*/
def staticModule(fullName: String): U#ModuleSymbol
/** The symbol corresponding to a package with the
* given fully qualified name `fullName`.
+ * @group Mirror
*/
def staticPackage(fullName: String): U#ModuleSymbol
}
diff --git a/src/reflect/scala/reflect/api/Mirrors.scala b/src/reflect/scala/reflect/api/Mirrors.scala
index bfd60dfba0..cc1b9762cb 100644
--- a/src/reflect/scala/reflect/api/Mirrors.scala
+++ b/src/reflect/scala/reflect/api/Mirrors.scala
@@ -1,13 +1,207 @@
package scala.reflect
package api
-/**
- * Defines a type hierarchy for mirrors.
+/** This trait provides support for Mirrors in the Scala Reflection API.
*
- * Every universe has one or more mirrors. A mirror defines a hierarchy of symbols starting with the root package `_root_`
- * and provides methods to locate and define classes and singleton objects in that hierarchy.
+ * `Mirror`s are a central part of Scala Reflection. All information provided by
+ * reflection is made accessible through `Mirror`s. Depending on the type of information
+ * to be obtained, or the reflective action to be taken, different flavors of mirrors
+ * must be used. "Classloader" mirrors can be used to obtain representations of types
+ * and members. From a classloader `Mirror`, it's possible to obtain more specialized
+ * "invoker" `Mirror`s (the most commonly-used mirrors), which implement reflective
+ * invocations, such as method/constructor calls and field accesses.
*
- * On the JVM, there is a one to one correspondance between class loaders and mirrors.
+ * The two flavors of mirrors:
+ *
+ * <ul>
+ * <li>```“Classloader” mirrors```. These mirrors translate names to symbols
+ * (via methods `staticClass`/`staticModule`/`staticPackage`).</li>
+ * <li>```"Invoker” mirrors```. These mirrors implement reflective invocations
+ * (via methods `MethodMirror.apply`, `FieldMirror.get`, etc). These "invoker"
+ * mirrors are the types of mirrors that are most commonly used.</li>
+ * </ul>
+ *
+ * === Compile-time Mirrors ===
+ * Compile-time `Mirror`s make use of only classloader `Mirror`s to load `Symbol`s
+ * by name.
+ *
+ * The entry point to classloader `Mirror`s is via [[scala.reflect.macros.Context#mirror]].
+ * Typical methods which use classloader `Mirror`s include [[scala.reflect.api.Mirror#staticClass]],
+ * [[scala.reflect.api.Mirror#staticModule]], and [[scala.reflect.api.Mirror#staticPackage]]. For
+ * example:
+ * {{{
+ * import scala.reflect.macros.Context
+ *
+ * case class Location(filename: String, line: Int, column: Int)
+ *
+ * object Macros {
+ * def currentLocation: Location = macro impl
+ *
+ * def impl(c: Context): c.Expr[Location] = {
+ * import c.universe._
+ * val pos = c.macroApplication.pos
+ * val clsLocation = c.mirror.staticModule("Location") // get symbol of "Location" object
+ * c.Expr(Apply(Ident(clsLocation), List(Literal(Constant(pos.source.path)), Literal(Constant(pos.line)), Literal(Constant(pos.column)))))
+ * }
+ * }
+ * }}}
+ *
+ * ''Of Note:'' There are several high-level alternatives that one can use to avoid having to manually
+ * lookup symbols. For example, `typeOf[Location.type].termSymbol` (or `typeOf[Location].typeSymbol`
+ * if we needed a `ClassSymbol`), which are type safe since we don’t have to use `String`s to lookup
+ * the `Symbol`.
+ *
+ * === Runtime Mirrors ===
+ *
+ * Runtime `Mirror`s make use of both classloader and invoker `Mirror`s.
+ *
+ * The entry point to `Mirror`s for use at runtime is via `ru.runtimeMirror(<classloader>)`, where
+ * `ru` is [[scala.reflect.runtime.universe]].
+ *
+ * The result of a [[scala.reflect.api.JavaMirrors#runtimeMirror]] call is a classloader mirror,
+ * of type [[scala.reflect.api.Mirrors#ReflectiveMirror]], which can load symbols by names as
+ * discussed above (in the “Compile-time” section).
+ *
+ * A classloader mirror can create invoker mirrors, which include: [[scala.reflect.api.Mirrors#InstanceMirror]],
+ * [[scala.reflect.api.Mirrors#MethodMirror]], [[scala.reflect.api.Mirrors#FieldMirror]],
+ * [[scala.reflect.api.Mirrors#ClassMirror]] and [[scala.reflect.api.Mirrors#ModuleMirror]].
+ *
+ * Examples of how these two types of `Mirror`s interact are available below.
+ *
+ * === Types of Mirrors, Their Use Cases & Examples ===
+ *
+ * '''[[scala.reflect.api.Mirrors#ReflectiveMirror]]'''. Used for loading `Symbol`s by name, and
+ * as an entry point into invoker mirrors. Entry point: `val m = ru.runtimeMirror(<classloader>)`.
+ * Example:
+ * {{{
+ * scala> val ru = scala.reflect.runtime.universe
+ * ru: scala.reflect.api.JavaUniverse = ...
+ *
+ * scala> val m = ru.runtimeMirror(getClass.getClassLoader)
+ * m: reflect.runtime.universe.Mirror = JavaMirror ...
+ * }}}
+ *
+ * '''[[scala.reflect.api.Mirrors#InstanceMirror]]'''. Used for creating invoker `Mirror`s for methods
+ * and fields and for inner classes and inner objects (modules). Entry point: `val im = m.reflect(<value>)`.
+ * Example:
+ * {{{
+ * scala> class C { def x = 2 }
+ * defined class C
+ *
+ * scala> val im = m.reflect(new C)
+ * im: reflect.runtime.universe.InstanceMirror = instance mirror for C@3442299e
+ * }}}
+ *
+ * '''[[scala.reflect.api.Mirrors#MethodMirror]]'''. Used for invoking instance methods (Scala only has
+ * instance methods-- methods of objects are instance methods of object instances, obtainable
+ * via `ModuleMirror.instance`). Entry point: `val mm = im.reflectMethod(<method symbol>)`.
+ * Example:
+ * {{{
+ * scala> val methodX = typeOf[C].declaration(newTermName("x")).asMethod
+ * methodX: reflect.runtime.universe.MethodSymbol = method x
+ *
+ * scala> val mm = im.reflectMethod(methodX)
+ * mm: reflect.runtime.universe.MethodMirror = method mirror for C.x: scala.Int (bound to C@3442299e)
+ *
+ * scala> mm()
+ * res0: Any = 2
+ * }}}
+ *
+ * '''[[scala.reflect.api.Mirrors#FieldMirror]]'''. Used for getting/setting instance fields
+ * (Scala only has instance fields-- fields of objects are instance methods of object instances
+ * obtainable via ModuleMirror.instance). Entry point:
+ * `val fm = im.reflectMethod(<field or accessor symbol>)`.
+ * Example:
+ * {{{
+ * scala> class C { val x = 2; val y = 3 }
+ * defined class C
+ *
+ * scala> val m = ru.runtimeMirror(getClass.getClassLoader)
+ * m: reflect.runtime.universe.Mirror = JavaMirror ...
+ *
+ * scala> val im = m.reflect(new C)
+ * im: reflect.runtime.universe.InstanceMirror = instance mirror for C@5f0c8ac1
+ *
+ * scala> val fieldX = typeOf[C].declaration(newTermName("x")).asTerm.accessed.asTerm
+ * fieldX: reflect.runtime.universe.TermSymbol = value x
+ * scala> val fmX = im.reflectField(fieldX)
+ * fmX: reflect.runtime.universe.FieldMirror = field mirror for C.x (bound to C@5f0c8ac1)
+ *
+ * scala> fmX.get
+ * res0: Any = 2
+ *
+ * scala> fmX.set(3)
+ * scala.ScalaReflectionException: cannot set an immutable field x
+ * ...
+ *
+ * scala> val fieldY = typeOf[C].declaration(newTermName("y")).asTerm.accessed.asTerm
+ * fieldY: reflect.runtime.universe.TermSymbol = variable y
+ *
+ * scala> val fmY = im.reflectField(fieldY)
+ * fmY: reflect.runtime.universe.FieldMirror = field mirror for C.y (bound to C@5f0c8ac1)
+ *
+ * scala> fmY.get
+ * res1: Any = 3
+ *
+ * scala> fmY.set(4)
+ *
+ * scala> fmY.get
+ * res2: Any = 4
+ * }}}
+ *
+ * '''[[scala.reflect.api.Mirrors#ClassMirror]]'''. Used for creating invoker mirrors for constructors.
+ * Entry points: for ''static classes'' `val cm1 = m.reflectClass(<class symbol>)`,
+ * for ''inner classes'' `val mm2 = im.reflectClass(<module symbol>)`.
+ * Example:
+ * {{{
+ * scala> case class C(x: Int)
+ * defined class C
+ *
+ * scala> val m = ru.runtimeMirror(getClass.getClassLoader)
+ * m: reflect.runtime.universe.Mirror = JavaMirror ...
+ *
+ * scala> val classC = typeOf[C].typeSymbol.asClass
+ *
+ * classC: reflect.runtime.universe.Symbol = class C
+ *
+ * scala> val cm = m.reflectClass(classC)
+ * cm: reflect.runtime.universe.ClassMirror = class mirror for C (bound to null)
+ *
+ * scala> val ctorC = typeOf[C].declaration(ru.nme.CONSTRUCTOR).asMethod
+ * ctorC: reflect.runtime.universe.MethodSymbol = constructor C
+ *
+ * scala> val ctorm = cm.reflectConstructor(ctorC)
+ * ctorm: reflect.runtime.universe.MethodMirror = constructor mirror for C.<init>(x: scala.Int): C (bound to null)
+ *
+ * scala> ctorm(2)
+ * res0: Any = C(2)
+ * }}}
+ *
+ * '''[[scala.reflect.api.Mirrors#ModuleMirror]]'''. Used for getting singleton instances of objects.
+ * Entry points: for ''static objects (modules)'' `val mm1 = m.reflectModule(<module symbol>)`,
+ * for ''inner objects (modules)'' `val mm2 = im.reflectModule(<module symbol>)`.
+ * Example:
+ * {{{
+ * scala> object C { def x = 2 }
+ * defined module C
+ *
+ * scala> val m = ru.runtimeMirror(getClass.getClassLoader)
+ * m: reflect.runtime.universe.Mirror = JavaMirror ...
+ *
+ * scala> val objectC = typeOf[C.type].termSymbol.asModule
+ * objectC: reflect.runtime.universe.ModuleSymbol = object C
+ *
+ * scala> val mm = m.reflectModule(objectC)
+ * mm: reflect.runtime.universe.ModuleMirror = module mirror for C (bound to null)
+ *
+ * scala> val obj = mm.instance
+ * obj: Any = C$@1005ec04
+ * }}}
+ *
+ * For more information about `Mirrors`s, see the
+ * [[http://docs.scala-lang.org/overviews/reflection/environment-universes-mirrors.html Reflection Guide: Mirrors]]
+ *
+ * @contentDiagram hideNodes "*Api"
*/
trait Mirrors { self: Universe =>
@@ -15,27 +209,35 @@ trait Mirrors { self: Universe =>
*
* This abstract type conforms the base interface for all mirrors defined in [[scala.reflect.api.Mirror]]
* and is gradually refined in specific universes (e.g. `Mirror` of a [[scala.reflect.api.JavaUniverse]] is capable of reflection).
+ * @group Mirrors
*/
type Mirror >: Null <: scala.reflect.api.Mirror[self.type]
/** The root mirror of this universe. This mirror contains standard Scala classes and types such as `Any`, `AnyRef`, `AnyVal`,
* `Nothing`, `Null`, and all classes loaded from scala-library, which are shared across all mirrors within the enclosing universe.
+ * @group Mirrors
*/
val rootMirror: Mirror
+ /** Abstracts the runtime representation of a class on the underlying platform.
+ * @group Mirrors
+ */
type RuntimeClass >: Null
// todo. an improvement might be having mirrors reproduce the structure of the reflection domain
// e.g. a ClassMirror could also have a list of fields, methods, constructors and so on
// read up more on the proposed design in "Reflecting Scala" by Y. Coppel
- /** A mirror that reflects a runtime value */
+ /** A mirror that reflects a runtime value.
+ * See [[scala.reflect.api.package the overview page]] for details on how to use runtime reflection.
+ * @group Mirrors
+ */
trait InstanceMirror {
/** The instance value reflected by this mirror */
def instance: Any
- /** The symbol corresponding to the run-time class of the reflected instance */
+ /** The symbol corresponding to the runtime class of the reflected instance */
def symbol: ClassSymbol
/** Reflects against a field symbol and returns a mirror
@@ -103,7 +305,10 @@ trait Mirrors { self: Universe =>
def reflectModule(mod: ModuleSymbol): ModuleMirror
}
- /** A mirror that reflects a field */
+ /** A mirror that reflects a field.
+ * See [[scala.reflect.api.package the overview page]] for details on how to use runtime reflection.
+ * @group Mirrors
+ */
trait FieldMirror {
/** The object containing the field */
@@ -145,7 +350,10 @@ trait Mirrors { self: Universe =>
def set(value: Any): Unit
}
- /** A mirror that reflects a method handle */
+ /** A mirror that reflects a method.
+ * See [[scala.reflect.api.package the overview page]] for details on how to use runtime reflection.
+ * @group Mirrors
+ */
trait MethodMirror {
/** The receiver object of the method */
@@ -163,7 +371,10 @@ trait Mirrors { self: Universe =>
def apply(args: Any*): Any
}
- /** A mirror that reflects the instance or static parts of a runtime class */
+ /** A mirror that reflects the instance or static parts of a runtime class.
+ * See [[scala.reflect.api.package the overview page]] for details on how to use runtime reflection.
+ * @group Mirrors
+ */
trait TemplateMirror {
/** True if the mirror represents the static part
@@ -179,7 +390,10 @@ trait Mirrors { self: Universe =>
def symbol: Symbol
}
- /** A mirror that reflects a Scala object definition or the static parts of a runtime class */
+ /** A mirror that reflects a Scala object definition or the static parts of a runtime class.
+ * See [[scala.reflect.api.package the overview page]] for details on how to use runtime reflection.
+ * @group Mirrors
+ */
trait ModuleMirror extends TemplateMirror {
/** The Scala module symbol corresponding to the reflected object */
@@ -192,7 +406,10 @@ trait Mirrors { self: Universe =>
def instance: Any
}
- /** A mirror that reflects the instance parts of a runtime class */
+ /** A mirror that reflects the instance parts of a runtime class.
+ * See [[scala.reflect.api.package the overview page]] for details on how to use runtime reflection.
+ * @group Mirrors
+ */
trait ClassMirror extends TemplateMirror {
/** The Scala class symbol corresponding to the reflected class */
@@ -211,7 +428,10 @@ trait Mirrors { self: Universe =>
def reflectConstructor(constructor: MethodSymbol): MethodMirror
}
- /** A mirror that reflects instances and static classes */
+ /** A mirror that reflects instances and static classes.
+ * See [[scala.reflect.api.package the overview page]] for details on how to use runtime reflection.
+ * @group Mirrors
+ */
trait ReflectiveMirror extends scala.reflect.api.Mirror[Mirrors.this.type] {
/** A reflective mirror for the given object.
@@ -246,7 +466,10 @@ trait Mirrors { self: Universe =>
def reflectModule(mod: ModuleSymbol): ModuleMirror
}
- /** The API of a mirror for a reflective universe */
+ /** The API of a mirror for a reflective universe.
+ * See [[scala.reflect.api.package the overview page]] for details on how to use runtime reflection.
+ * @group Mirrors
+ */
trait RuntimeMirror extends ReflectiveMirror { self =>
/** Maps a Scala type to the corresponding Java class object */
diff --git a/src/reflect/scala/reflect/api/Names.scala b/src/reflect/scala/reflect/api/Names.scala
index 6cb226c32f..02eb79f8ed 100644
--- a/src/reflect/scala/reflect/api/Names.scala
+++ b/src/reflect/scala/reflect/api/Names.scala
@@ -1,40 +1,70 @@
package scala.reflect
package api
-/** A trait that manages names.
+/** This trait defines Names (a Scala reflection concept) and operations on them.
*
- * @see TermName
- * @see TypeName
+ * Names are simple wrappers for strings. [[scala.reflect.api.Names#Name Name]] has two subtypes [[scala.reflect.api.Names#TermName TermName]] and [[scala.reflect.api.Names#TypeName TypeName]] which
+ * distinguish names of terms (like objects or members) and types. A term and a type of the
+ * same name can co-exist in an object.
+ *
+ * === Examples ===
+ *
+ * To search for the `map` method (which is a term) declared in the `List` class,
+ * use `typeOf[List[_]].member(newTermName("map"))`. To search for a type member, use
+ * newTypeName instead.
+ *
+ * See the [[docs.scala-lang.org/overviews/reflection/overview.html Reflection Guide]] for more about Scala Reflection.
+ *
+ * @contentDiagram hideNodes "*Api"
*/
trait Names {
- // Intentionally no implicit from String => Name.
+ /** An implicit conversion from String to TermName.
+ * Enables an alternative notation `"map": TermName` as opposed to `newTermName("map")`.
+ * @group Names
+ */
implicit def stringToTermName(s: String): TermName = newTermName(s)
+
+ /** An implicit conversion from String to TypeName.
+ * Enables an alternative notation `"List": TypeName` as opposed to `newTypeName("List")`.
+ * @group Names
+ */
implicit def stringToTypeName(s: String): TypeName = newTypeName(s)
- /**
- * The abstract type of names
- *
- * A Name wraps a string as the name for either a type ([[TypeName]]) of a term ([[TermName]]).
- * Two names are equal, if the wrapped string are equal and they are either both `TypeName` or both `TermName`.
- * The same string can co-exist as a `TypeName` and a `TermName`, but they would not be equal.
- * Names are interned. That is, for two names `name11 and `name2`,
- * `name1 == name2` implies `name1 eq name2`.
- *
- * One of the reasons for the existence of names rather than plain strings is being more explicit about what is a name and if it represents a type or a term.
+ /** The abstract type of names.
+ * @group Names
*/
type Name >: Null <: NameApi
+
+ /** A tag that preserves the identity of the `Name` abstract type from erasure.
+ * Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
+ */
implicit val NameTag: ClassTag[Name]
- /** The abstract type of names representing terms */
+ /** The abstract type of names representing terms.
+ * @group Names
+ */
type TypeName >: Null <: Name
- implicit val TypeNameTag: ClassTag[TypeName]
- /** The abstract type of names representing types */
+ /** A tag that preserves the identity of the `TypeName` abstract type from erasure.
+ * Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
+ */
+implicit val TypeNameTag: ClassTag[TypeName]
+
+ /** The abstract type of names representing types.
+ * @group Names
+ */
type TermName >: Null <: Name
+
+ /** A tag that preserves the identity of the `TermName` abstract type from erasure.
+ * Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
+ */
implicit val TermNameTag: ClassTag[TermName]
- /** The API of names that's supported on reflect mirror via an
- * implicit conversion in reflect.ops
+ /** The API of Name instances.
+ * @group API
*/
abstract class NameApi {
/** Checks wether the name is a a term name */
@@ -69,10 +99,12 @@ trait Names {
}
/** Create a new term name.
+ * @group Names
*/
def newTermName(s: String): TermName
/** Creates a new type name.
+ * @group Names
*/
def newTypeName(s: String): TypeName
}
diff --git a/src/reflect/scala/reflect/api/Position.scala b/src/reflect/scala/reflect/api/Position.scala
index d3dc9c884f..61d643b449 100644
--- a/src/reflect/scala/reflect/api/Position.scala
+++ b/src/reflect/scala/reflect/api/Position.scala
@@ -3,64 +3,63 @@ package api
import scala.reflect.macros.Attachments
-/** The Position class and its subclasses represent positions of ASTs and symbols.
- * Except for NoPosition and FakePos, every position refers to a SourceFile
- * and to an offset in the sourcefile (its `point`). For batch compilation,
- * that's all. For interactive IDE's there are also RangePositions
- * and TransparentPositions. A RangePosition indicates a start and an end
- * in addition to its point. TransparentPositions are a subclass of RangePositions.
- * Range positions that are not transparent are called opaque.
- * Trees with RangePositions need to satisfy the following invariants.
+/** Position tracks the origin of [[Symbols#Symbol symbols]] and [[Trees#Tree tree nodes]]. They are commonly used when
+ * displaying warnings and errors, to indicate the incorrect point in the program.
*
- * INV1: A tree with an offset position never contains a child
+ * A position indicates the [[source source file]] and an [[point offset]]. A position may be
+ * undefined, which means it's pointing to the [[Positions#NoPosition]] element.
+ *
+ * <b>Please note that this trait may be refactored in future versions of the Scala reflection API.</b>
+ *
+ * @see [[http://docs.scala-lang.org/overviews/reflection/names-exprs-scopes-more.html]]
+ *
+ * The compiler adds more information to positions, such a ranges in the source file and defines different types of
+ * positions depending on how a symbol or tree node was generated. The guide fully describes compiler-generated positions.
+ *
+ * - INV1: A tree with an offset position never contains a child
* with a range position
- * INV2: If the child of a tree with a range position also has a range position,
+ * - INV2: If the child of a tree with a range position also has a range position,
* then the child's range is contained in the parent's range.
- * INV3: Opaque range positions of children of the same node are non-overlapping
+ * - INV3: Opaque range positions of children of the same node are non-overlapping
* (this means their overlap is at most a single point).
*
* The following tests are useful on positions:
- *
- * pos.isDefined true if position is not a NoPosition nor a FakePosition
- * pos.isRange true if position is a range
- * pos.isOpaqueRange true if position is an opaque range
- *
- * The following accessor methods are provided:
- *
- * pos.source The source file of the position, which must be defined
- * pos.point The offset of the position's point, which must be defined
- * pos.start The start of the position, which must be a range
- * pos.end The end of the position, which must be a range
+ * `pos.isDefined` true if position is not a NoPosition,
+ * `pos.isRange` true if position is a range,
+ * `pos.isOpaqueRange` true if position is an opaque range,
*
* There are also convenience methods, such as
- *
- * pos.startOrPoint
- * pos.endOrPoint
- * pos.pointOrElse(default)
- *
+ * `pos.startOrPoint`,
+ * `pos.endOrPoint`,
+ * `pos.pointOrElse(default)`.
* These are less strict about the kind of position on which they can be applied.
*
* The following conversion methods are often used:
+ * `pos.focus` converts a range position to an offset position, keeping its point;
+ * returns all other positions unchanged,
+ * `pos.makeTransparent` converts an opaque range position into a transparent one.
+ * returns all other positions unchanged.
*
- * pos.focus converts a range position to an offset position, keeping its point;
- * returns all other positions unchanged.
- * pos.makeTransparent converts an opaque range position into a transparent one.
- * returns all other positions unchanged.
+ * @groupname Common Commonly used methods
*/
trait Position extends Attachments {
+ /** @inheritdoc */
type Pos >: Null <: Position
/** Java file corresponding to the source file of this position.
*
- * The return type is [[scala.reflect.io.AbstractFile]], which belongs to an experimental part of Scala reflection.
+ * The return type is `scala.reflect.io.AbstractFile`, which belongs to an experimental part of Scala reflection.
* It should not be used unless you know what you are doing. In subsequent releases, this API will be refined
* and exposed as a part of scala.reflect.api.
+ *
+ * @group Common
*/
def source: scala.reflect.internal.util.SourceFile
/** Is this position neither a NoPosition nor a FakePosition?
* If isDefined is true, offset and source are both defined.
+ * @group Common
*/
def isDefined: Boolean
@@ -71,36 +70,46 @@ trait Position extends Attachments {
def isTransparent: Boolean
/** Is this position a non-transparent range position? */
- def isOpaqueRange: Boolean
+ def isOpaqueRange: Boolean
- /** if opaque range, make this position transparent */
+ /** If opaque range, make this position transparent. */
def makeTransparent: Pos
- /** The start of the position's range, error if not a range position */
+ /** The start of the position's range, error if not a range position. */
def start: Int
- /** The start of the position's range, or point if not a range position */
+ /** The start of the position's range, or point if not a range position. */
def startOrPoint: Int
- /** The point (where the ^ is) of the position */
+ /** The point (where the ^ is) of the position, which is easiest to access using the [[line]] and [[column]] values.
+ * The [[lineContent line content]] is also available.
+ * @group Common
+ */
def point: Int
- /** The point (where the ^ is) of the position, or else `default` if undefined */
+ /** The point (where the ^ is) of the position, or else `default` if undefined.
+ * @group Common
+ */
def pointOrElse(default: Int): Int
- /** The end of the position's range, error if not a range position */
+ /** The end of the position's range, error if not a range position.
+ */
def end: Int
- /** The end of the position's range, or point if not a range position */
+ /** The end of the position's range, or point if not a range position.
+ */
def endOrPoint: Int
- /** The same position with a different start value (if a range) */
+ /** The same position with a different start value (if a range).
+ */
def withStart(off: Int): Pos
- /** The same position with a different end value (if a range) */
+ /** The same position with a different end value (if a range).
+ */
def withEnd(off: Int): Pos
- /** The same position with a different point value (if a range or offset) */
+ /** The same position with a different point value (if a range or offset).
+ */
def withPoint(off: Int): Pos
/** If this is a range, the union with the other range, with the point of this position.
@@ -123,7 +132,7 @@ trait Position extends Attachments {
*/
def focusEnd: Pos
- /** Does this position include the given position `pos`.
+ /** Does this position include the given position `pos`?
* This holds if `this` is a range position and its range [start..end]
* is the same or covers the range of the given position, which may or may not be a range position.
*/
@@ -156,14 +165,26 @@ trait Position extends Attachments {
*/
def sameRange(pos: Pos): Boolean
+ /** The position indicates a [[column `column`]] and the `line` in the source file.
+ * @group Common
+ */
def line: Int
+ /** The position indicates a `column` and the [[line `line`]] in the source file.
+ * @group Common
+ */
def column: Int
- /** Convert this to a position around `point` that spans a single source line */
+ /** Convert this to a position around `point` that spans a single source line
+ */
def toSingleLine: Pos
+ /** The content of the line this Position refers to.
+ * @group Common
+ */
def lineContent: String
+ /** Show a textual representation of the position.
+ */
def show: String
}
diff --git a/src/reflect/scala/reflect/api/Positions.scala b/src/reflect/scala/reflect/api/Positions.scala
index 5c530e7e70..8d8a0081cc 100644
--- a/src/reflect/scala/reflect/api/Positions.scala
+++ b/src/reflect/scala/reflect/api/Positions.scala
@@ -1,26 +1,34 @@
package scala.reflect
package api
-/**
- * Defines the type hierachy for positions.
+/** This trait defines the concept of positions and operations on them.
*
- * @see [[scala.reflect]] for a description on how the class hierarchy is encoded here.
+ * @see [[scala.reflect.api.Position]]
+ *
+ * @contentDiagram hideNodes "*Api"
*/
trait Positions {
self: Universe =>
- /** .. */
+ /** Defines a universe-specific notion of positions.
+ * The main documentation entry about positions is located at [[scala.reflect.api.Position]].
+ * @group Positions
+ */
type Position >: Null <: scala.reflect.api.Position { type Pos = Position }
/** A tag that preserves the identity of the `Position` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val PositionTag: ClassTag[Position]
- /** A special "missing" position. */
+ /** A special "missing" position.
+ * @group Positions
+ */
val NoPosition: Position
/** Assigns a given position to all position-less nodes of a given AST.
+ * @group Positions
*/
def atPos[T <: Tree](pos: Position)(tree: T): T
@@ -28,6 +36,7 @@ trait Positions {
* The point of the wrapping position is the point of the default position.
* If some of the trees are ranges, returns a range position enclosing all ranges
* Otherwise returns default position.
+ * @group Positions
*/
def wrappingPos(default: Position, trees: List[Tree]): Position
@@ -35,6 +44,7 @@ trait Positions {
* The point of the wrapping position is the point of the first trees' position.
* If all some the trees are non-synthetic, returns a range position enclosing the non-synthetic trees
* Otherwise returns a synthetic offset position to point.
+ * @group Positions
*/
def wrappingPos(trees: List[Tree]): Position
}
diff --git a/src/reflect/scala/reflect/api/Printers.scala b/src/reflect/scala/reflect/api/Printers.scala
index 72a9bf8f3d..1e8161aeef 100644
--- a/src/reflect/scala/reflect/api/Printers.scala
+++ b/src/reflect/scala/reflect/api/Printers.scala
@@ -3,8 +3,134 @@ package api
import java.io.{ PrintWriter, StringWriter }
+/** Utilities for nicely printing [[scala.reflect.api.Trees]] and [[scala.reflect.api.Types]].
+ *
+ * === Printing Trees ===
+ * The method `show` displays the "prettified" representation of reflection artifacts.
+ * This representation provides one with the desugared Java representation of Scala code.
+ * For example:
+ *
+ * {{{
+ * scala> import scala.reflect.runtime.universe._
+ * import scala.reflect.runtime.universe._
+ *
+ * scala> def tree = reify{ final class C { def x = 2 } }.tree
+ * tree: reflect.runtime.universe.Tree
+ *
+ * scala> show(tree)
+ * res0: String =
+ * {
+ * final class C extends AnyRef {
+ * def <init>() = {
+ * super.<init>();
+ * ()
+ * };
+ * def x = 2
+ * };
+ * ()
+ * }
+ * }}}
+ *
+ * The method `showRaw` displays internal structure of a given reflection object
+ * as a Scala abstract syntax tree (AST), the representation that the Scala typechecker
+ * operates on.
+ *
+ * Note, that while this representation appears to generate correct trees that one
+ * might think would be possible to use in a macro implementation, this is not usually
+ * the case. Symbols aren't fully represented (only their names are). Thus, this method
+ * is best-suited for use simply inspecting ASTs given some valid Scala code.
+ * {{{
+ * scala> showRaw(tree)
+ * res1: String = Block(List(
+ * ClassDef(Modifiers(FINAL), newTypeName("C"), List(), Template(
+ * List(Ident(newTypeName("AnyRef"))),
+ * emptyValDef,
+ * List(
+ * DefDef(Modifiers(), nme.CONSTRUCTOR, List(), List(List()), TypeTree(),
+ * Block(List(
+ * Apply(Select(Super(This(tpnme.EMPTY), tpnme.EMPTY), nme.CONSTRUCTOR), List())),
+ * Literal(Constant(())))),
+ * DefDef(Modifiers(), newTermName("x"), List(), List(), TypeTree(),
+ * Literal(Constant(2))))))),
+ * Literal(Constant(())))
+ * }}}
+ *
+ * The method `showRaw` can also print [[scala.reflect.api.Types]] next to the artifacts
+ * being inspected
+ * {{{
+ * scala> import scala.tools.reflect.ToolBox // requires scala-compiler.jar
+ * import scala.tools.reflect.ToolBox
+ *
+ * scala> import scala.reflect.runtime.{currentMirror => cm}
+ * import scala.reflect.runtime.{currentMirror=>cm}
+ *
+ * scala> showRaw(cm.mkToolBox().typeCheck(tree), printTypes = true)
+ * res2: String = Block[1](List(
+ * ClassDef[2](Modifiers(FINAL), newTypeName("C"), List(), Template[3](
+ * List(Ident[4](newTypeName("AnyRef"))),
+ * emptyValDef,
+ * List(
+ * DefDef[2](Modifiers(), nme.CONSTRUCTOR, List(), List(List()), TypeTree[3](),
+ * Block[1](List(
+ * Apply[4](Select[5](Super[6](This[3](newTypeName("C")), tpnme.EMPTY), ...))),
+ * Literal[1](Constant(())))),
+ * DefDef[2](Modifiers(), newTermName("x"), List(), List(), TypeTree[7](),
+ * Literal[8](Constant(2))))))),
+ * Literal[1](Constant(())))
+ * [1] TypeRef(ThisType(scala), scala.Unit, List())
+ * [2] NoType
+ * [3] TypeRef(NoPrefix, newTypeName("C"), List())
+ * [4] TypeRef(ThisType(java.lang), java.lang.Object, List())
+ * [5] MethodType(List(), TypeRef(ThisType(java.lang), java.lang.Object, List()))
+ * [6] SuperType(ThisType(newTypeName("C")), TypeRef(... java.lang.Object ...))
+ * [7] TypeRef(ThisType(scala), scala.Int, List())
+ * [8] ConstantType(Constant(2))
+ * }}}
+ *
+ * === Printing Types ===
+ *
+ * The method `show`
+ * {{{
+ * scala> import scala.reflect.runtime.universe._
+ * import scala.reflect.runtime.universe._
+ *
+ * scala> def tpe = typeOf[{ def x: Int; val y: List[Int] }]
+ * tpe: reflect.runtime.universe.Type
+ *
+ * scala> show(tpe)
+ * res0: String = scala.AnyRef{def x: Int; val y: scala.List[Int]}
+ * }}}
+ *
+ * Like the method `showRaw` for [[scala.reflect.api.Trees]], `showRaw`
+ * for [[scala.reflect.api.Types]] provides a visualization of the Scala
+ * AST operated on by the Scala typechecker.
+ * {{{
+ * // showRaw has already been discussed above
+ * scala> showRaw(tpe)
+ * res1: String = RefinedType(
+ * List(TypeRef(ThisType(scala), newTypeName("AnyRef"), List())),
+ * Scope(
+ * newTermName("x"),
+ * newTermName("y")))
+ * }}}
+ *
+ * `printIds` and/or `printKinds` can additionally be supplied as arguments in a call to
+ * `showRaw` which additionally shows the unique identifiers of symbols.
+ * scala> showRaw(tpe, printIds = true, printKinds = true)
+ * res2: String = RefinedType(
+ * List(TypeRef(ThisType(scala#2043#PK), newTypeName("AnyRef")#691#TPE, List())),
+ * Scope(
+ * newTermName("x")#2540#METH,
+ * newTermName("y")#2541#GET))
+ * }}}
+ *
+ * For more details about `Printer`s and other aspects of Scala reflection, see the
+ * [[http://docs.scala-lang.org/overviews/reflection/overview.html Reflection Guide]]
+ *
+ */
trait Printers { self: Universe =>
+ /** @group Printers */
protected trait TreePrinter {
def print(args: Any*)
protected var printTypes = false
@@ -21,13 +147,16 @@ trait Printers { self: Universe =>
def withoutMirrors: this.type = { printMirrors = false; this }
}
+ /** @group Printers */
case class BooleanFlag(val value: Option[Boolean])
+ /** @group Printers */
object BooleanFlag {
import scala.language.implicitConversions
implicit def booleanToBooleanFlag(value: Boolean): BooleanFlag = BooleanFlag(Some(value))
implicit def optionToBooleanFlag(value: Option[Boolean]): BooleanFlag = BooleanFlag(value)
}
+ /** @group Printers */
protected def render(what: Any, mkPrinter: PrintWriter => TreePrinter, printTypes: BooleanFlag = None, printIds: BooleanFlag = None, printKinds: BooleanFlag = None, printMirrors: BooleanFlag = None): String = {
val buffer = new StringWriter()
val writer = new PrintWriter(buffer)
@@ -41,41 +170,54 @@ trait Printers { self: Universe =>
buffer.toString
}
- /** By default trees are printed with `show` */
+ /** By default trees are printed with `show`
+ * @group Printers
+ */
override protected def treeToString(tree: Tree) = show(tree)
- /** Renders a prettified representation of a reflection artifact.
- * Typically it looks very close to the Scala code it represents.
+ /** Renders a representation of a reflection artifact
+ * as desugared Java code.
+ *
+ * @group Printers
*/
def show(any: Any, printTypes: BooleanFlag = None, printIds: BooleanFlag = None, printKinds: BooleanFlag = None, printMirrors: BooleanFlag = None): String =
render(any, newTreePrinter(_), printTypes, printIds, printKinds, printMirrors)
/** Hook to define what `show(...)` means.
+ * @group Printers
*/
protected def newTreePrinter(out: PrintWriter): TreePrinter
- /** Renders internal structure of a reflection artifact.
+ /** Renders internal structure of a reflection artifact as the
+ * visualization of a Scala syntax tree.
+ *
+ * @group Printers
*/
def showRaw(any: Any, printTypes: BooleanFlag = None, printIds: BooleanFlag = None, printKinds: BooleanFlag = None, printMirrors: BooleanFlag = None): String =
render(any, newRawTreePrinter(_), printTypes, printIds, printKinds, printMirrors)
/** Hook to define what `showRaw(...)` means.
+ * @group Printers
*/
protected def newRawTreePrinter(out: PrintWriter): TreePrinter
/** Renders a prettified representation of a name.
+ * @group Printers
*/
def show(name: Name): String
/** Renders internal structure of a name.
+ * @group Printers
*/
def showRaw(name: Name): String = name.toString
/** Renders a prettified representation of a flag set.
+ * @group Printers
*/
def show(flags: FlagSet): String
/** Renders internal structure of a flag set.
+ * @group Printers
*/
def showRaw(flags: FlagSet): String = flags.toString
}
diff --git a/src/reflect/scala/reflect/api/Scopes.scala b/src/reflect/scala/reflect/api/Scopes.scala
index 770349c5b5..80683c8e76 100644
--- a/src/reflect/scala/reflect/api/Scopes.scala
+++ b/src/reflect/scala/reflect/api/Scopes.scala
@@ -1,33 +1,53 @@
package scala.reflect
package api
-/**
- * Defines the type hierachy for scopes.
+/** This trait provides support for scopes in the reflection API.
*
- * @see [[scala.reflect]] for a description on how the class hierarchy is encoded here.
+ * A scope object generally maps names to symbols available in a corresponding lexical scope.
+ * Scopes can be nested. The base type exposed to the reflection API, however,
+ * only exposes a minimal interface, representing a scope as an iterable of symbols.
+ *
+ * For rare occasions when it is necessary to create a scope manually,
+ * e.g., to populate members of [[scala.reflect.api.Types#RefinedType]],
+ * there is the `newScopeWith` function.
+ *
+ * Additional functionality is exposed in member scopes that are returned by
+ * `members` and `declarations` defined in [[scala.reflect.api.Types#TypeApi]].
+ * Such scopes support the `sorted` method, which sorts members in declaration order.
*/
trait Scopes { self: Universe =>
- /** The base type of all scopes. A scope object generally maps names to symbols available in the current lexical scope.
- * Scopes can be nested. This base type, however, only exposes a minimal interface, representing a scope as an iterable of symbols.
+ /** The base type of all scopes.
+ * @template
+ * @group Scopes
*/
type Scope >: Null <: ScopeApi
- /** The API that all scopes support */
+ /** The API that all scopes support
+ * @group API
+ */
trait ScopeApi extends Iterable[Symbol]
/** A tag that preserves the identity of the `Scope` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val ScopeTag: ClassTag[Scope]
- /** Create a new scope with the given initial elements. */
+ /** Create a new scope with the given initial elements.
+ * @group Scopes
+ */
def newScopeWith(elems: Symbol*): Scope
- /** The type of member scopes, as in class definitions, for example. */
+ /** The type of member scopes, as in class definitions, for example.
+ * @template
+ * @group Scopes
+ */
type MemberScope >: Null <: Scope with MemberScopeApi
- /** The API that all member scopes support */
+ /** The API that all member scopes support
+ * @group API
+ */
trait MemberScopeApi extends ScopeApi {
/** Sorts the symbols included in this scope so that:
* 1) Symbols appear in the linearization order of their owners.
@@ -39,6 +59,7 @@ trait Scopes { self: Universe =>
/** A tag that preserves the identity of the `MemberScope` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val MemberScopeTag: ClassTag[MemberScope]
} \ No newline at end of file
diff --git a/src/reflect/scala/reflect/api/StandardDefinitions.scala b/src/reflect/scala/reflect/api/StandardDefinitions.scala
index 7197542370..a31a501357 100644
--- a/src/reflect/scala/reflect/api/StandardDefinitions.scala
+++ b/src/reflect/scala/reflect/api/StandardDefinitions.scala
@@ -5,128 +5,305 @@
package scala.reflect
package api
-/**
- * Defines standard symbols and types.
+/** All Scala standard symbols and types.
+ *
+ * These standard definitions can accessed to using `definitions`.
+ * They're typically imported with a blanket import `import definitions`, and are
+ * listed in [[scala.reflect.api.StandardDefinitions#DefinitionsApi]].
*/
trait StandardDefinitions {
self: Universe =>
- /** A value containing all standard defnitions. */
+ /** A value containing all standard definitions in [[DefinitionsApi]]
+ * @group Definitions
+ */
val definitions: DefinitionsApi
- /** Defines standard symbols (and types via its base trait). */
+ /** Defines standard symbols (and types via its base trait).
+ * @group API
+ */
trait DefinitionsApi extends StandardTypes {
- /** The class symbol of package `scala`. */
+ /** The module class symbol of package `scala`. */
def ScalaPackageClass: ClassSymbol
- /** The module class symbol of package `scala`. */
+ /** The module symbol of package `scala`. */
def ScalaPackage: ModuleSymbol
- // top types
+ /** The class symbol of core class `scala.Any`. */
def AnyClass : ClassSymbol
+
+ /** The class symbol of core class `scala.AnyVal`. */
def AnyValClass: ClassSymbol
+
+ /** The class symbol of core class `java.lang.Object`. */
def ObjectClass: ClassSymbol
+
+ /** The type symbol of core class `scala.AnyRef`. */
def AnyRefClass: TypeSymbol
- // bottom types
+ /** The class symbol of core class `scala.Null`. */
def NullClass : ClassSymbol
+
+ /** The class symbol of core class `scala.Nothing`. */
def NothingClass: ClassSymbol
- // the scala value classes
+ /** The class symbol of primitive class `scala.Unit`. */
def UnitClass : ClassSymbol
+
+ /** The class symbol of primitive class `scala.Byte`. */
def ByteClass : ClassSymbol
+
+ /** The class symbol of primitive class `scala.Short`. */
def ShortClass : ClassSymbol
+
+ /** The class symbol of primitive class `scala.Char`. */
def CharClass : ClassSymbol
+
+ /** The class symbol of primitive class `scala.Int`. */
def IntClass : ClassSymbol
+
+ /** The class symbol of primitive class `scala.Long`. */
def LongClass : ClassSymbol
+
+ /** The class symbol of primitive class `scala.Float`. */
def FloatClass : ClassSymbol
+
+ /** The class symbol of primitive class `scala.Double`. */
def DoubleClass : ClassSymbol
+
+ /** The class symbol of primitive class `scala.Boolean`. */
def BooleanClass: ClassSymbol
- /** The class symbol of class `String`. */
+ /** The class symbol of class `scala.String`. */
def StringClass : ClassSymbol
- /** The class symbol of class `Class`. */
+ /** The class symbol of class `java.lang.Class`. */
def ClassClass : ClassSymbol
- /** The class symbol of class `Array`. */
+ /** The class symbol of class `scala.Array`. */
def ArrayClass : ClassSymbol
- /** The class symbol of class `List`. */
+ /** The class symbol of class `scala.List`. */
def ListClass : ClassSymbol
- /** The module symbol of `scala.Predef`. */
+ /** The module symbol of module `scala.Predef`. */
def PredefModule: ModuleSymbol
+ /** The module class symbol of package `java.lang`. */
def JavaLangPackageClass: ClassSymbol
+
+ /** The module symbol of package `java.lang`. */
def JavaLangPackage: ModuleSymbol
+
+ /** The module symbol of module `scala.Array`. */
def ArrayModule: ModuleSymbol
+
+ /** The method symbol of method `apply` in module `scala.Array`. */
def ArrayModule_overloadedApply: TermSymbol // todo. fix the bug in Definitions.getMemberMethod
+
+ /** The method symbol of method `apply` in class `scala.Array`. */
def Array_apply: TermSymbol // todo. fix the bug in Definitions.getMemberMethod
+
+ /** The method symbol of method `clone` in class `scala.Array`. */
def Array_clone: TermSymbol // todo. fix the bug in Definitions.getMemberMethod
+
+ /** The method symbol of method `length` in class `scala.Array`. */
def Array_length: TermSymbol // todo. fix the bug in Definitions.getMemberMethod
+
+ /** The method symbol of method `update` in class `scala.Array`. */
def Array_update: TermSymbol // todo. fix the bug in Definitions.getMemberMethod
+
+ /** A dummy class symbol that is used to indicate by-name parameters.
+ *
+ * {{{
+ * scala> class C { def m(x: => Int) = ??? }
+ * defined class C
+ *
+ * scala> import scala.reflect.runtime.universe._
+ * import scala.reflect.runtime.universe._
+ *
+ * scala> val m = typeOf[C].member(newTermName("m")).asMethod
+ * m: reflect.runtime.universe.MethodSymbol = method m
+ *
+ * scala> m.params(0)(0).typeSignature
+ * res1: reflect.runtime.universe.Type = => scala.Int
+ *
+ * scala> showRaw(m.params(0)(0).typeSignature)
+ * res2: String = TypeRef(
+ * ThisType(scala),
+ * scala.<byname>, // <-- ByNameParamClass
+ * List(TypeRef(ThisType(scala), scala.Int, List())))
+ * }}}
+ */
def ByNameParamClass: ClassSymbol
- def FunctionClass : Array[ClassSymbol]
+
+ /** A dummy class symbol that is used to indicate repeated parameters
+ * compiled by the Java compiler.
+ *
+ * {{{
+ * class C {
+ * public void m(Object... x) {}
+ * }
+ * }}}
+ *
+ * {{{
+ * scala> import scala.reflect.runtime.universe._
+ * import scala.reflect.runtime.universe._
+ *
+ * scala> val m = typeOf[C].member(newTermName("m")).asMethod
+ * m: reflect.runtime.universe.MethodSymbol = method m
+ *
+ * scala> m.params(0)(0).typeSignature
+ * res1: reflect.runtime.universe.Type = <repeated...>[Object]
+ *
+ * scala> showRaw(m.params(0)(0).typeSignature)
+ * res2: String = TypeRef(
+ * ThisType(scala),
+ * scala.<repeated...>, // <-- JavaRepeatedParamClass
+ * List(TypeRef(ThisType(java.lang), Object, List())))
+ * }}}
+ */
def JavaRepeatedParamClass: ClassSymbol
+
+ /** A dummy class symbol that is used to indicate repeated parameters
+ * compiled by the Scala compiler.
+ *
+ * {{{
+ * scala> class C { def m(x: Int*) = ??? }
+ * defined class C
+ *
+ * scala> import scala.reflect.runtime.universe._
+ * import scala.reflect.runtime.universe._
+ *
+ * scala> val m = typeOf[C].member(newTermName("m")).asMethod
+ * m: reflect.runtime.universe.MethodSymbol = method m
+ *
+ * scala> m.params(0)(0).typeSignature
+ * res1: reflect.runtime.universe.Type = scala.Int*
+ *
+ * scala> showRaw(m.params(0)(0).typeSignature)
+ * res2: String = TypeRef(
+ * ThisType(scala),
+ * scala.<repeated>, // <-- RepeatedParamClass
+ * List(TypeRef(ThisType(scala), scala.Int, List())))
+ * }}}
+ */
+ def RepeatedParamClass: ClassSymbol
+
+ /** The module symbol of module `scala.List`. */
def ListModule: ModuleSymbol
+
+ /** The method symbol of method `apply` in class `scala.List`. */
def List_apply: TermSymbol // todo. fix the bug in Definitions.getMemberMethod
+
+ /** The module symbol of module `scala.collection.immutable.Nil`. */
def NilModule: ModuleSymbol
- def NoneModule: ModuleSymbol
+
+ /** The class symbol of class `scala.Option`. */
def OptionClass: ClassSymbol
- def ProductClass : Array[ClassSymbol]
- def RepeatedParamClass: ClassSymbol
+
+ /** The module symbol of module `scala.None`. */
+ def NoneModule: ModuleSymbol
+
+ /** The module symbol of module `scala.Some`. */
def SomeModule: ModuleSymbol
+
+ /** The array of class symbols for classes `scala.ProductX`.
+ * - 0th element is `Unit`
+ * - 1st element is `Product1`
+ * - ...
+ * - 22nd element is `Product22`
+ */
+ def ProductClass : Array[ClassSymbol]
+
+ /** The array of class symbols for classes `scala.FunctionX`.
+ * - 0th element is `Function0`
+ * - 1st element is `Function1`
+ * - ...
+ * - 22nd element is `Function22`
+ */
+ def FunctionClass : Array[ClassSymbol]
+
+ /** The array of class symbols for classes `scala.TupleX`.
+ * - 0th element is `NoSymbol`
+ * - 1st element is `Product1`
+ * - ...
+ * - 22nd element is `Product22`
+ */
def TupleClass: Array[Symbol] // cannot make it Array[ClassSymbol], because TupleClass(0) is supposed to be NoSymbol. weird
+
+ /** Contains Scala primitive value classes:
+ * - Byte
+ * - Short
+ * - Int
+ * - Long
+ * - Float
+ * - Double
+ * - Char
+ * - Boolean
+ * - Unit
+ */
def ScalaPrimitiveValueClasses: List[ClassSymbol]
+
+ /** Contains Scala numeric value classes:
+ * - Byte
+ * - Short
+ * - Int
+ * - Long
+ * - Float
+ * - Double
+ * - Char
+ */
def ScalaNumericValueClasses: List[ClassSymbol]
}
- /** Defines standard types. */
+ /** Defines standard types.
+ * @group Definitions
+ */
trait StandardTypes {
- /** The `Type` of type `Unit`. */
+ /** The type of primitive type `Unit`. */
val UnitTpe: Type
- /** The `Type` of primitive type `Byte`. */
+ /** The type of primitive type `Byte`. */
val ByteTpe: Type
- /** The `Type` of primitive type `Short`. */
+ /** The type of primitive type `Short`. */
val ShortTpe: Type
- /** The `Type` of primitive type `Char`. */
+ /** The type of primitive type `Char`. */
val CharTpe: Type
- /** The `Type` of primitive type `Int`. */
+ /** The type of primitive type `Int`. */
val IntTpe: Type
- /** The `Type` of primitive type `Long`. */
+ /** The type of primitive type `Long`. */
val LongTpe: Type
- /** The `Type` of primitive type `Float`. */
+ /** The type of primitive type `Float`. */
val FloatTpe: Type
- /** The `Type` of primitive type `Double`. */
+ /** The type of primitive type `Double`. */
val DoubleTpe: Type
- /** The `Type` of primitive type `Boolean`. */
+ /** The type of primitive type `Boolean`. */
val BooleanTpe: Type
- /** The `Type` of type `Any`. */
+ /** The type of core type `Any`. */
val AnyTpe: Type
- /** The `Type` of type `AnyVal`. */
+ /** The type of core type `AnyVal`. */
val AnyValTpe: Type
- /** The `Type` of type `AnyRef`. */
+ /** The type of core type `AnyRef`. */
val AnyRefTpe: Type
- /** The `Type` of type `Object`. */
+ /** The type of core type `Object`. */
val ObjectTpe: Type
- /** The `Type` of type `Nothing`. */
+ /** The type of core type `Nothing`. */
val NothingTpe: Type
- /** The `Type` of type `Null`. */
+ /** The type of core type `Null`. */
val NullTpe: Type
}
}
diff --git a/src/reflect/scala/reflect/api/StandardNames.scala b/src/reflect/scala/reflect/api/StandardNames.scala
index 36ba840c84..fc18c02706 100644
--- a/src/reflect/scala/reflect/api/StandardNames.scala
+++ b/src/reflect/scala/reflect/api/StandardNames.scala
@@ -10,33 +10,95 @@ package api
// Is it necessary to perform reflection (like ERROR or LOCAL_SUFFIX_STRING)? If yes, then sure.
// Otherwise you'd better not - reflection API should stay minimalistic.
-// TODO: document better
/**
- * Names necessary to create Scala trees.
+ * Standard names are names that are essential to creating trees or to reflecting Scala artifacts.
+ * For example, `CONSTRUCTOR` (aka `<init>` on JVM) is necessary to create and invoke constructors.
+ *
+ * These standard names can be referred to using [[nme `nme`]] for term names and [[tpnme `tpnme`]] for type names
+ *
+ * @see [[Names]]
+ *
+ * The API for names in Scala reflection.
+ * @groupname StandardNames Standard Names
*/
trait StandardNames {
self: Universe =>
+ /** A value containing all [[TermNamesApi standard term names]].
+ * @group StandardNames
+ */
val nme: TermNamesApi
+
+ /** A value containing all [[TypeNamesApi standard type names]].
+ * @group StandardNames
+ */
val tpnme: TypeNamesApi
+ /** Defines standard names, common for term and type names: These can be accessed via the [[nme]] and [[tpnme]] members.
+ * @group API
+ */
trait NamesApi {
+ /** An abstract type that represents the exact flavor of the name. */
type NameType >: Null <: Name
+
+ /** The term or type name `_`.
+ * Used to construct trees that correspond to underscores in Scala.
+ */
val WILDCARD: NameType
+
+ /** The term or type name corresponding to an empty string.
+ * Represents an empty name, used to denote the fact that no name was specified
+ * for `privateWithin` in [[Trees#Modifiers]], for [[Trees#This]],
+ * for [[Trees#Super]], etc.
+ */
val EMPTY: NameType
+
+ /** The term or type name `<error>`.
+ * Indicates that the enclosing tree or symbol contains a compilation error.
+ */
val ERROR: NameType
+
+ /** The term or type name `package`.
+ * Used to get modules representing package objects.
+ */
val PACKAGE: NameType
}
+ /** Defines standard term names that can be accessed via the [[nme]] member.
+ * @group API
+ */
trait TermNamesApi extends NamesApi {
+ /** @inheritdoc */
type NameType = TermName
+
+ /** The term name `<init>`.
+ * Represents the constructor name on the JVM.
+ */
val CONSTRUCTOR: NameType
+
+ /** The term name `_root_`.
+ * Represents the root package.
+ */
val ROOTPKG: NameType
+
+ /** The string " " (a single whitespace).
+ * `LOCAL_SUFFIX_STRING` is appended to the names of local identifiers,
+ * when it's necessary to prevent a naming conflict. For example, underlying fields
+ * of non-private vals and vars are renamed using `LOCAL_SUFFIX_STRING`.
+ */
val LOCAL_SUFFIX_STRING: String
}
+ /** Defines standard type names that can be accessed via the [[tpnme]] member.
+ * @group API
+ */
trait TypeNamesApi extends NamesApi {
+ /** @inheritdoc */
type NameType = TypeName
+
+ /** The type name `_*`.
+ * Used to construct types that specify sequence arguments to repeated parameters.
+ */
val WILDCARD_STAR: NameType
}
}
diff --git a/src/reflect/scala/reflect/api/Symbols.scala b/src/reflect/scala/reflect/api/Symbols.scala
index e456428338..993cbd97a5 100644
--- a/src/reflect/scala/reflect/api/Symbols.scala
+++ b/src/reflect/scala/reflect/api/Symbols.scala
@@ -1,85 +1,164 @@
package scala.reflect
package api
-/**
- * Defines the type hierachy for symbols
+/** This trait defines symbols and operations on them.
*
- * @see [[scala.reflect]] for a description on how the class hierarchy is encoded here.
+ * Symbols are used to establish bindings between a name and the entity it refers to, such as a class or a method.
+ * Anything you define and can give a name to in Scala has an associated symbol.
+ *
+ * Certain types of tree nodes, such as [[Trees#Ident Ident]] (references to identifiers) and
+ * [[Trees#Select Select]] (references to members) expose method [[Trees.SymTreeApi.symbol `symbol`]]
+ * to obtain the symbol that represents their declaration. During the typechecking phase, the compiler looks up the
+ * symbol based on the name and scope and sets the [[Trees.SymTreeApi.symbol `symbol` field]] of tree nodes.
+ *
+ * @contentDiagram hideNodes "*Api"
+ *
+ * @see [[http://docs.scala-lang.org/overviews/reflection/overview.html]]
+ *
+ * The Reflection Guide provides more details on symbol usage and attached intricacies.
+ *
+ * @define SYMACCESSORS Class [[Symbol]] defines `isXXX` test methods such as `isPublic` or `isFinal`, `params` and
+ * `returnType` methods for method symbols, `baseClasses` for class symbols and so on. Some of these methods don't
+ * make sense for certain subclasses of `Symbol` and return `NoSymbol`, `Nil` or other empty values.
*/
trait Symbols { self: Universe =>
- /** The type of symbols representing declarations */
+ /** The type of symbols representing declarations.
+ * @group Symbols
+ * @template
+ */
type Symbol >: Null <: SymbolApi
/** A tag that preserves the identity of the `Symbol` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val SymbolTag: ClassTag[Symbol]
/** The type of type symbols representing type, class, and trait declarations,
- * as well as type parameters
+ * as well as type parameters.
+ * @group Symbols
+ * @template
*/
type TypeSymbol >: Null <: Symbol with TypeSymbolApi
/** A tag that preserves the identity of the `TypeSymbol` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val TypeSymbolTag: ClassTag[TypeSymbol]
/** The type of term symbols representing val, var, def, and object declarations as
* well as packages and value parameters.
+ * @group Symbols
+ * @template
*/
type TermSymbol >: Null <: Symbol with TermSymbolApi
/** A tag that preserves the identity of the `TermSymbol` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val TermSymbolTag: ClassTag[TermSymbol]
- /** The type of method symbols representing def declarations */
+ /** The type of method symbols representing def declarations.
+ * @group Symbols
+ * @template
+ */
type MethodSymbol >: Null <: TermSymbol with MethodSymbolApi
/** A tag that preserves the identity of the `MethodSymbol` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val MethodSymbolTag: ClassTag[MethodSymbol]
- /** The type of module symbols representing object declarations */
+ /** The type of module symbols representing object declarations.
+ * @group Symbols
+ * @template
+ */
type ModuleSymbol >: Null <: TermSymbol with ModuleSymbolApi
/** A tag that preserves the identity of the `ModuleSymbol` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val ModuleSymbolTag: ClassTag[ModuleSymbol]
- /** The type of class symbols representing class and trait definitions */
+ /** The type of class symbols representing class and trait definitions.
+ * @group Symbols
+ * @template
+ */
type ClassSymbol >: Null <: TypeSymbol with ClassSymbolApi
/** A tag that preserves the identity of the `ClassSymbol` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val ClassSymbolTag: ClassTag[ClassSymbol]
- /** The type of free terms introduced by reification */
+ /** The type of free terms introduced by reification.
+ * @group Symbols
+ * @template
+ */
type FreeTermSymbol >: Null <: TermSymbol with FreeTermSymbolApi
/** A tag that preserves the identity of the `FreeTermSymbol` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val FreeTermSymbolTag: ClassTag[FreeTermSymbol]
- /** The type of free types introduced by reification */
+ /** The type of free types introduced by reification.
+ * @group Symbols
+ * @template
+ */
type FreeTypeSymbol >: Null <: TypeSymbol with FreeTypeSymbolApi
/** A tag that preserves the identity of the `FreeTypeSymbol` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val FreeTypeSymbolTag: ClassTag[FreeTypeSymbol]
- /** A special "missing" symbol */
+ /** A special "missing" symbol. Commonly used in the API to denote a default or empty value.
+ * @group Symbols
+ * @template
+ */
val NoSymbol: Symbol
- /** The API of symbols */
+ /** The API of symbols.
+ * The main source of information about symbols is the [[Symbols]] page.
+ *
+ * $SYMACCESSORS
+ * @group API
+ * @groupname Basics Symbol Basic Information
+ * @groupprio Basics 0
+ * @groupname Tests Symbol Type Tests
+ * @groupprio Tests 1
+ * @groupname Conversions Symbol Conversions
+ * @groupprio Conversions 2
+ * @groupname Constructors New Symbol Constructors
+ * @groupprio Constructors 3
+ * @groupdesc Constructors These methods construct new symbols owned by the current symbol.
+ * @groupname Helpers Iteration Helpers
+ * @groupprio Helpers 4
+ * @groupdesc Helpers These methods enable collections-like operations on symbols.
+ * @groupname Type TypeSymbol Members
+ * @groupprio Type -1
+ * @groupname FreeType FreeType Symbol Members
+ * @groupprio FreeType -2
+ * @groupname Term TermSymbol Members
+ * @groupprio Term -1
+ * @groupname FreeTerm FreeTerm Symbol Members
+ * @groupprio FreeTerm -2
+ * @groupname Class Class Symbol Members
+ * @groupprio Class -2
+ * @groupname Method Method Symbol Members
+ * @groupprio Method -2
+ * @groupname Module Module Symbol Members
+ * @groupprio Module -2
+ */
trait SymbolApi { this: Symbol =>
/** The owner of this symbol. This is the symbol
@@ -90,6 +169,8 @@ trait Symbols { self: Universe =>
* and the Scala root object [[scala.reflect.api.Mirror.RootPackage]] is `NoSymbol`.
* Every other symbol has a chain of owners that ends in
* [[scala.reflect.api.Mirror.RootClass]].
+ *
+ * @group Basics
*/
def owner: Symbol
@@ -98,15 +179,18 @@ trait Symbols { self: Universe =>
*
* Type name namespaces do not intersect with term name namespaces.
* This fact is reflected in different types for names of `TermSymbol` and `TypeSymbol`.
+ * @group Basics
*/
type NameType >: Null <: Name
/** The name of the symbol as a member of the `Name` type.
+ * @group Basics
*/
def name: Name
/** The encoded full path name of this symbol, where outer names and inner names
* are separated by periods.
+ * @group Basics
*/
def fullName: String
@@ -114,11 +198,15 @@ trait Symbols { self: Universe =>
* Note that every symbol is either a term or a type.
* So for every symbol `sym` (except for `NoSymbol`),
* either `sym.isTerm` is true or `sym.isType` is true.
+ *
+ * @group Tests
*/
def isType: Boolean = false
/** This symbol cast to a TypeSymbol.
* @throws ScalaReflectionException if `isType` is false.
+ *
+ * @group Conversions
*/
def asType: TypeSymbol = throw new ScalaReflectionException(s"$this is not a type")
@@ -126,21 +214,29 @@ trait Symbols { self: Universe =>
* Note that every symbol is either a term or a type.
* So for every symbol `sym` (except for `NoSymbol`),
* either `sym.isTerm` is true or `sym.isTerm` is true.
+ *
+ * @group Tests
*/
def isTerm: Boolean = false
/** This symbol cast to a TermSymbol.
* @throws ScalaReflectionException if `isTerm` is false.
+ *
+ * @group Conversions
*/
def asTerm: TermSymbol = throw new ScalaReflectionException(s"$this is not a term")
/** Does this symbol represent the definition of a method?
* If yes, `isTerm` is also guaranteed to be true.
+ *
+ * @group Tests
*/
def isMethod: Boolean = false
/** This symbol cast to a MethodSymbol.
* @throws ScalaReflectionException if `isMethod` is false.
+ *
+ * @group Conversions
*/
def asMethod: MethodSymbol = {
def overloadedMsg =
@@ -151,92 +247,135 @@ trait Symbols { self: Universe =>
throw new ScalaReflectionException(s"$this $msg")
}
- /** Used to provide a better error message for `asMethod` */
+ /** Used to provide a better error message for `asMethod`
+ *
+ * @group Tests
+ */
protected def isOverloadedMethod = false
/** Does this symbol represent the definition of a module (i.e. it
* results from an object definition?).
* If yes, `isTerm` is also guaranteed to be true.
+ *
+ * @group Tests
*/
def isModule: Boolean = false
/** This symbol cast to a ModuleSymbol defined by an object definition.
* @throws ScalaReflectionException if `isModule` is false.
+ *
+ * @group Conversions
*/
def asModule: ModuleSymbol = throw new ScalaReflectionException(s"$this is not a module")
/** Does this symbol represent the definition of a class or trait?
* If yes, `isType` is also guaranteed to be true.
+ *
+ * @group Tests
*/
def isClass: Boolean = false
/** Does this symbol represent the definition of a class implicitly associated
* with an object definition (module class in scala compiler parlance).
* If yes, `isType` is also guaranteed to be true.
+ *
+ * @group Tests
*/
def isModuleClass: Boolean = false
/** This symbol cast to a ClassSymbol representing a class or trait.
* @throws ScalaReflectionException if `isClass` is false.
+ *
+ * @group Conversions
*/
def asClass: ClassSymbol = throw new ScalaReflectionException(s"$this is not a class")
/** Does this symbol represent a free term captured by reification?
* If yes, `isTerm` is also guaranteed to be true.
+ *
+ * @group Tests
*/
def isFreeTerm: Boolean = false
/** This symbol cast to a free term symbol.
* @throws ScalaReflectionException if `isFreeTerm` is false.
+ *
+ * @group Conversions
*/
def asFreeTerm: FreeTermSymbol = throw new ScalaReflectionException(s"$this is not a free term")
/** Does this symbol represent a free type captured by reification?
* If yes, `isType` is also guaranteed to be true.
+ *
+ * @group Tests
*/
def isFreeType: Boolean = false
/** This symbol cast to a free type symbol.
* @throws ScalaReflectionException if `isFreeType` is false.
+ *
+ * @group Conversions
*/
def asFreeType: FreeTypeSymbol = throw new ScalaReflectionException(s"$this is not a free type")
+ /** @group Constructors */
def newTermSymbol(name: TermName, pos: Position = NoPosition, flags: FlagSet = NoFlags): TermSymbol
+ /** @group Constructors */
def newModuleAndClassSymbol(name: Name, pos: Position = NoPosition, flags: FlagSet = NoFlags): (ModuleSymbol, ClassSymbol)
+ /** @group Constructors */
def newMethodSymbol(name: TermName, pos: Position = NoPosition, flags: FlagSet = NoFlags): MethodSymbol
+ /** @group Constructors */
def newTypeSymbol(name: TypeName, pos: Position = NoPosition, flags: FlagSet = NoFlags): TypeSymbol
+ /** @group Constructors */
def newClassSymbol(name: TypeName, pos: Position = NoPosition, flags: FlagSet = NoFlags): ClassSymbol
/** Source file if this symbol is created during this compilation run,
* or a class file if this symbol is loaded from a *.class or *.jar.
*
- * The return type is [[scala.reflect.io.AbstractFile]], which belongs to an experimental part of Scala reflection.
+ * The return type is `scala.reflect.io.AbstractFile`, which belongs to an experimental part of Scala reflection.
* It should not be used unless you know what you are doing. In subsequent releases, this API will be refined
* and exposed as a part of scala.reflect.api.
+ *
+ * @group Basics
*/
def associatedFile: scala.reflect.io.AbstractFile
/** A list of annotations attached to this Symbol.
+ *
+ * @group Basics
*/
def annotations: List[Annotation]
/** For a class: the module or case class factory with the same name in the same package.
* For a module: the class with the same name in the same package.
* For all others: NoSymbol
+ *
+ * @group Basics
*/
def companionSymbol: Symbol
/** The type signature of this symbol seen as a member of given type `site`.
+ *
+ * @group Basics
*/
def typeSignatureIn(site: Type): Type
/** The type signature of this symbol.
- * Note if the symbol is a member of a class, one almost always is interested
- * in `typeSignatureIn` with a site type instead.
+ *
+ * This method always returns signatures in the most generic way possible, even if the underlying symbol is obtained from an
+ * instantiation of a generic type. For example, signature
+ * of the method `def map[B](f: (A) ⇒ B): List[B]`, which refers to the type parameter `A` of the declaring class `List[A]`,
+ * will always feature `A`, regardless of whether `map` is loaded from the `List[_]` or from `List[Int]`. To get a signature
+ * with type parameters appropriately instantiated, one should use `typeSignatureIn`.
+ *
+ * @group Basics
*/
def typeSignature: Type
- /** Returns all symbols overriden by this symbol. */
+ /** Returns all symbols overriden by this symbol.
+ *
+ * @group Basics
+ */
def allOverriddenSymbols: List[Symbol]
/******************* tests *******************/
@@ -244,11 +383,15 @@ trait Symbols { self: Universe =>
/** Does this symbol represent a synthetic (i.e. a compiler-generated) entity?
* Examples of synthetic entities are accessors for vals and vars
* or mixin constructors in trait implementation classes.
+ *
+ * @group Tests
*/
def isSynthetic: Boolean
/** Does this symbol represent an implementation artifact that isn't meant for public use?
- * Examples of such artifacts are erasure bridges and $outer fields.
+ * Examples of such artifacts are erasure bridges and outer fields.
+ *
+ * @group Tests
*/
def isImplementationArtifact: Boolean
@@ -258,20 +401,28 @@ trait Symbols { self: Universe =>
* Local symbols can only be accessed from the same object instance.
*
* If yes, `privateWithin` might tell more about this symbol's visibility scope.
+ *
+ * @group Tests
*/
def isLocal: Boolean
/** Does this symbol represent a private declaration or definition?
* If yes, `privateWithin` might tell more about this symbol's visibility scope.
+ *
+ * @group Tests
*/
def isPrivate: Boolean
/** Does this symbol represent a protected declaration or definition?
* If yes, `privateWithin` might tell more about this symbol's visibility scope.
+ *
+ * @group Tests
*/
def isProtected: Boolean
/** Does this symbol represent a public declaration or definition?
+ *
+ * @group Tests
*/
def isPublic: Boolean
@@ -299,20 +450,28 @@ trait Symbols { self: Universe =>
* java package: !isPrivate && !isProtected && (privateWithin == enclosingPackage)
* java protected: isProtected && (privateWithin == enclosingPackage)
* java public: !isPrivate && !isProtected && (privateWithin == NoSymbol)
+ *
+ * @group Tests
*/
def privateWithin: Symbol
/** Does this symbol represent the definition of a package?
* If yes, `isTerm` is also guaranteed to be true.
+ *
+ * @group Tests
*/
def isPackage: Boolean
/** Does this symbol represent a package class?
* If yes, `isClass` is also guaranteed to be true.
+ *
+ * @group Tests
*/
def isPackageClass: Boolean
/** Does this symbol or its underlying type represent a typechecking error?
+ *
+ * @group Tests
*/
def isErroneous : Boolean
@@ -320,62 +479,96 @@ trait Symbols { self: Universe =>
* Q: When exactly is a sym marked as STATIC?
* A: If it's a member of a toplevel object, or of an object contained in a toplevel object, or any number of levels deep.
* http://groups.google.com/group/scala-internals/browse_thread/thread/d385bcd60b08faf6
+ *
+ * @group Tests
*/
def isStatic: Boolean
/** Is this symbol final?
+ *
+ * @group Tests
*/
def isFinal: Boolean
/** Is this symbol overriding something?
+ *
+ * @group Tests
*/
def isOverride: Boolean
/** Is this symbol labelled as "abstract override"?
+ *
+ * @group Tests
*/
def isAbstractOverride: Boolean
/** Is this symbol a macro?
+ *
+ * @group Tests
*/
def isMacro: Boolean
/** Is this symbol a parameter (either a method parameter or a type parameter)?
+ *
+ * @group Tests
*/
def isParameter: Boolean
/** Is this symbol a specialized type parameter or a generated specialized member?
+ *
+ * @group Tests
*/
def isSpecialized: Boolean
/** Is this symbol defined by Java?
+ *
+ * @group Tests
*/
def isJava: Boolean
/** Does this symbol represent an implicit value, definition, class or parameter?
+ *
+ * @group Tests
*/
def isImplicit: Boolean
/******************* helpers *******************/
- /** ...
+ /** Provides an alternate if symbol is a NoSymbol.
+ *
+ * @group Helpers
*/
def orElse(alt: => Symbol): Symbol
- /** ...
+ /** Filters the underlying alternatives (or a single-element list
+ * composed of the symbol itself if the symbol is not overloaded).
+ * Returns an overloaded symbol is there are multiple matches.
+ * Returns a NoSymbol if there are no matches.
+ *
+ * @group Helpers
*/
def filter(cond: Symbol => Boolean): Symbol
/** If this is a NoSymbol, returns NoSymbol, otherwise
* returns the result of applying `f` to this symbol.
+ *
+ * @group Helpers
*/
def map(f: Symbol => Symbol): Symbol
- /** ...
+ /** Does the same as `filter`, but crashes if there are multiple matches.
+ *
+ * @group Helpers
*/
def suchThat(cond: Symbol => Boolean): Symbol
}
- /** The API of term symbols */
+ /** The API of term symbols.
+ * The main source of information about symbols is the [[Symbols]] page.
+ *
+ * $SYMACCESSORS
+ * @group API
+ */
trait TermSymbolApi extends SymbolApi { this: TermSymbol =>
/** Term symbols have their names of type `TermName`.
*/
@@ -385,78 +578,117 @@ trait Symbols { self: Universe =>
final override def asTerm = this
/** Is this symbol introduced as `val`?
+ *
+ * @group Term
*/
def isVal: Boolean
- /** Does this symbol denote a stable value? */
+ /** Does this symbol denote a stable value?
+ *
+ * @group Term
+ */
def isStable: Boolean
/** Is this symbol introduced as `var`?
+ *
+ * @group Term
*/
def isVar: Boolean
/** Does this symbol represent a getter or a setter?
+ *
+ * @group Term
*/
def isAccessor: Boolean
/** Does this symbol represent a getter of a field?
* If yes, `isMethod` is also guaranteed to be true.
+ *
+ * @group Term
*/
def isGetter: Boolean
/** Does this symbol represent a setter of a field?
* If yes, `isMethod` is also guaranteed to be true.
+ *
+ * @group Term
*/
def isSetter: Boolean
/** Does this symbol represent an overloaded method?
* If yes, `isMethod` is false, and the list of the enclosed alternatives can be found out via `alternatives`.
+ *
+ * @group Term
*/
def isOverloaded : Boolean
/** Does this symbol represent a lazy value?
+ *
+ * @group Term
*/
def isLazy: Boolean
- /** The overloaded alternatives of this symbol */
+ /** The overloaded alternatives of this symbol
+ *
+ * @group Term
+ */
def alternatives: List[Symbol]
/** Used to provide a better error message for `asMethod` */
override protected def isOverloadedMethod = alternatives exists (_.isMethod)
/** Backing field for an accessor method, NoSymbol for all other term symbols.
+ *
+ * @group Term
*/
def accessed: Symbol
/** Getter method for a backing field of a val or a val, NoSymbol for all other term symbols.
+ *
+ * @group Term
*/
def getter: Symbol
/** Setter method for a backing field of a val or a val, NoSymbol for all other term symbols.
+ *
+ * @group Term
*/
def setter: Symbol
/** Does this symbol represent a field of a class
* that was generated from a parameter of that class?
+ *
+ * @group Term
*/
def isParamAccessor: Boolean
/** Does this symbol represent a field of a case class
* that corresponds to a parameter in the first parameter list of the
* primary constructor of that class?
+ *
+ * @group Term
*/
def isCaseAccessor: Boolean
/** Does this symbol represent a parameter with a default value?
+ *
+ * @group Term
*/
def isParamWithDefault: Boolean
/** Does this symbol represent a by-name parameter?
+ *
+ * @group Term
*/
def isByNameParam: Boolean
}
- /** The API of type symbols */
+ /** The API of type symbols.
+ * The main source of information about symbols is the [[Symbols]] page.
+ *
+ * $SYMACCESSORS
+ * @group API
+ */
trait TypeSymbolApi extends SymbolApi { this: TypeSymbol =>
/** Type symbols have their names of type `TypeName`.
*/
@@ -468,11 +700,15 @@ trait Symbols { self: Universe =>
*
* Example: Given a class declaration `class C[T] { ... } `, that generates a symbol
* `C`. Then `C.toType` is the type `C[T]`, but `C.toTypeConstructor` is `C`.
+ *
+ * @group Type
*/
def toTypeConstructor: Type
/** A type reference that refers to this type symbol seen
* as a member of given type `site`.
+ *
+ * @group Type
*/
def toTypeIn(site: Type): Type
@@ -486,42 +722,64 @@ trait Symbols { self: Universe =>
* By contrast, `C.typeSignature` would be a type signature of form
* `PolyType(ClassInfoType(...))` that describes type parameters, value
* parameters, parent types, and members of `C`.
- */
+ *
+ * @group Type
+ */
def toType: Type
final override def isType = true
final override def asType = this
/** Is the type parameter represented by this symbol contravariant?
+ *
+ * @group Type
*/
def isContravariant : Boolean
/** Is the type parameter represented by this symbol contravariant?
+ *
+ * @group Type
*/
def isCovariant : Boolean
/** Does this symbol represent the definition of a skolem?
* Skolems are used during typechecking to represent type parameters viewed from inside their scopes.
+ *
+ * @group Type
*/
def isSkolem : Boolean
/** Does this symbol represent the definition of a type alias?
+ *
+ * @group Type
*/
def isAliasType : Boolean
/** Does this symbol represent the definition of an abstract type?
+ *
+ * @group Type
*/
def isAbstractType : Boolean
/** Does this symbol represent an existentially bound type?
+ *
+ * @group Type
*/
def isExistential : Boolean
- /** For a polymorphic type, its type parameters, the empty list for all other types */
+ /** For a polymorphic type, its type parameters, the empty list for all other types
+ *
+ * @group Type
+ */
def typeParams: List[Symbol]
}
- /** The API of method symbols */
+ /** The API of method symbols.
+ * The main source of information about symbols is the [[Symbols]] page.
+ *
+ * $SYMACCESSORS
+ * @group API
+ */
trait MethodSymbolApi extends TermSymbolApi { this: MethodSymbol =>
final override def isMethod = true
final override def asMethod = this
@@ -530,13 +788,21 @@ trait Symbols { self: Universe =>
*
* If `owner` is a class, then this is a vanilla JVM constructor.
* If `owner` is a trait, then this is a mixin constructor.
+ *
+ * @group Method
*/
def isConstructor: Boolean
- /** Does this symbol denote the primary constructor of its enclosing class? */
+ /** Does this symbol denote the primary constructor of its enclosing class?
+ *
+ * @group Method
+ */
def isPrimaryConstructor: Boolean
- /** For a polymorphic method, its type parameters, the empty list for all other methods */
+ /** For a polymorphic method, its type parameters, the empty list for all other methods
+ *
+ * @group Method
+ */
def typeParams: List[Symbol]
/** All parameter lists of the method.
@@ -545,22 +811,36 @@ trait Symbols { self: Universe =>
* Can be used to distinguish nullary methods and methods with empty parameter lists.
* For a nullary method, returns the empty list (i.e. `List()`).
* For a method with an empty parameter list, returns a list that contains the empty list (i.e. `List(List())`).
+ *
+ * @group Method
*/
def paramss: List[List[Symbol]]
/** Does this method support variable length argument lists?
+ *
+ * @group Method
*/
def isVarargs: Boolean
- /** The return type of the method */
+ /** The return type of the method
+ *
+ * @group Method
+ */
def returnType: Type
}
- /** The API of module symbols */
+ /** The API of module symbols.
+ * The main source of information about symbols is the [[Symbols]] page.
+ *
+ * $SYMACCESSORS
+ * @group API
+ */
trait ModuleSymbolApi extends TermSymbolApi { this: ModuleSymbol =>
/** The class implicitly associated with the object definition.
* One can go back from a module class to the associated module symbol
* by inspecting its `selfType.termSymbol`.
+ *
+ * @group Module
*/
def moduleClass: Symbol // needed for tree traversals
// when this becomes `moduleClass: ClassSymbol`, it will be the happiest day in my life
@@ -569,7 +849,12 @@ trait Symbols { self: Universe =>
final override def asModule = this
}
- /** The API of class symbols */
+ /** The API of class symbols.
+ * The main source of information about symbols is the [[Symbols]] page.
+ *
+ * $SYMACCESSORS
+ * @group API
+ */
trait ClassSymbolApi extends TypeSymbolApi { this: ClassSymbol =>
final override def isClass = true
final override def asClass = this
@@ -577,82 +862,129 @@ trait Symbols { self: Universe =>
/** Does this symbol represent the definition of a primitive class?
* Namely, is it one of [[scala.Double]], [[scala.Float]], [[scala.Long]], [[scala.Int]], [[scala.Char]],
* [[scala.Short]], [[scala.Byte]], [[scala.Unit]] or [[scala.Boolean]]?
+ *
+ * @group Class
*/
def isPrimitive: Boolean
/** Does this symbol represent the definition of a numeric value class?
* Namely, is it one of [[scala.Double]], [[scala.Float]], [[scala.Long]], [[scala.Int]], [[scala.Char]],
* [[scala.Short]], [[scala.Byte]], [[scala.Unit]] or [[scala.Boolean]]?
+ *
+ * @group Class
*/
def isNumeric: Boolean
/** Does this symbol represent the definition of a custom value class?
* Namely, is AnyVal among its parent classes?
+ *
+ * @group Class
*/
def isDerivedValueClass: Boolean
/** Does this symbol represent a trait?
+ *
+ * @group Class
*/
def isTrait: Boolean
/** Does this symbol represent an abstract class?
+ *
+ * @group Class
*/
def isAbstractClass: Boolean
/** Does this symbol represent a case class?
+ *
+ * @group Class
*/
def isCaseClass: Boolean
/** Does this symbol represent a sealed class?
+ *
+ * @group Class
*/
def isSealed: Boolean
/** If this is a sealed class, its known direct subclasses.
* Otherwise, the empty set.
+ *
+ * @group Class
*/
def knownDirectSubclasses: Set[Symbol]
/** The list of all base classes of this type (including its own typeSymbol)
* in reverse linearization order, starting with the class itself and ending
* in class Any.
+ *
+ * @group Class
*/
def baseClasses: List[Symbol]
/** The module corresponding to this module class,
* or NoSymbol if this symbol is not a module class.
+ *
+ * @group Class
*/
def module: Symbol
/** If this symbol is a class or trait, its self type, otherwise the type
* of the symbol itself.
+ *
+ * @group Class
*/
def selfType: Type
- /** The type `C.this`, where `C` is the current class */
+ /** The type `C.this`, where `C` is the current class
+ *
+ * @group Class
+ */
def thisPrefix: Type
- /** For a polymorphic class/trait, its type parameters, the empty list for all other classes/trait */
+ /** For a polymorphic class/trait, its type parameters, the empty list for all other classes/trait
+ *
+ * @group Class
+ */
def typeParams: List[Symbol]
}
- /** The API of free term symbols */
+ /** The API of free term symbols.
+ * The main source of information about symbols is the [[Symbols]] page.
+ *
+ * $SYMACCESSORS
+ * @group API
+ */
trait FreeTermSymbolApi extends TermSymbolApi { this: FreeTermSymbol =>
final override def isFreeTerm = true
final override def asFreeTerm = this
- /** The place where this symbol has been spawned */
+ /** The place where this symbol has been spawned
+ *
+ * @group FreeTerm
+ */
def origin: String
- /** The valus this symbol refers to */
+ /** The valus this symbol refers to
+ *
+ * @group FreeTerm
+ */
def value: Any
}
- /** The API of free term symbols */
+ /** The API of free type symbols.
+ * The main source of information about symbols is the [[Symbols]] page.
+ *
+ * $SYMACCESSORS
+ * @group API
+ */
trait FreeTypeSymbolApi extends TypeSymbolApi { this: FreeTypeSymbol =>
final override def isFreeType = true
final override def asFreeType = this
- /** The place where this symbol has been spawned */
+ /** The place where this symbol has been spawned
+ *
+ * @group FreeType
+ */
def origin: String
}
}
diff --git a/src/reflect/scala/reflect/api/TagInterop.scala b/src/reflect/scala/reflect/api/TagInterop.scala
index fc0558d717..4e43f59706 100644
--- a/src/reflect/scala/reflect/api/TagInterop.scala
+++ b/src/reflect/scala/reflect/api/TagInterop.scala
@@ -1,26 +1,37 @@
package scala.reflect
package api
+/** This trait provides type tag <-> manifest interoperability.
+ * @groupname TagInterop TypeTag and Manifest Interoperability
+ */
trait TagInterop { self: Universe =>
// TODO `mirror` parameters are now of type `Any`, because I can't make these path-dependent types work
// if you're brave enough, replace `Any` with `Mirror`, recompile and run interop_typetags_are_manifests.scala
/**
- * Convert a typetag to a pre `Scala-2.10` manifest.
- * For example
+ * Convert a [[scala.reflect.api.TypeTags#TypeTag]] to a [[scala.reflect.Manifest]].
+ *
+ * Compiler usually generates these conversions automatically, when a type tag for a type `T` is in scope,
+ * and an implicit of type `Manifest[T]` is requested, but this method can also be called manually.
+ * For example:
* {{{
- * typeTagToManifest( scala.reflect.runtime.currentMirror, implicitly[TypeTag[String]] )
+ * typeTagToManifest(scala.reflect.runtime.currentMirror, implicitly[TypeTag[String]])
* }}}
+ * @group TagInterop
*/
def typeTagToManifest[T: ClassTag](mirror: Any, tag: Universe#TypeTag[T]): Manifest[T] =
throw new UnsupportedOperationException("This universe does not support tag -> manifest conversions. Use a JavaUniverse, e.g. the scala.reflect.runtime.universe.")
/**
- * Convert a pre `Scala-2.10` manifest to a typetag.
- * For example
+ * Convert a [[scala.reflect.Manifest]] to a [[scala.reflect.api.TypeTags#TypeTag]].
+ *
+ * Compiler usually generates these conversions automatically, when a manifest for a type `T` is in scope,
+ * and an implicit of type `TypeTag[T]` is requested, but this method can also be called manually.
+ * For example:
* {{{
- * manifestToTypeTag( scala.reflect.runtime.currentMirror, implicitly[Manifest[String]] )
+ * manifestToTypeTag(scala.reflect.runtime.currentMirror, implicitly[Manifest[String]])
* }}}
+ * @group TagInterop
*/
def manifestToTypeTag[T](mirror: Any, manifest: Manifest[T]): Universe#TypeTag[T] =
throw new UnsupportedOperationException("This universe does not support manifest -> tag conversions. Use a JavaUniverse, e.g. the scala.reflect.runtime.universe.")
diff --git a/src/reflect/scala/reflect/api/TreeCreator.scala b/src/reflect/scala/reflect/api/TreeCreator.scala
index a8e8ae1b58..cba90b72e6 100644
--- a/src/reflect/scala/reflect/api/TreeCreator.scala
+++ b/src/reflect/scala/reflect/api/TreeCreator.scala
@@ -1,25 +1,9 @@
package scala.reflect
package api
-/** A mirror-aware factory for trees.
+/** This is an internal implementation class.
*
- * In the reflection API, artifacts are specific to universes and
- * symbolic references used in artifacts (e.g. `scala.Int`) are resolved by mirrors.
- *
- * Therefore to build a tree one needs to know a universe that the tree is going to be bound to
- * and a mirror that is going to resolve symbolic references (e.g. to determine that `scala.Int`
- * points to a core class `Int` from scala-library.jar).
- *
- * `TreeCreator` implements this notion by providing a standalone tree factory.
- *
- * This is immediately useful for reification. When the compiler reifies an expression,
- * the end result needs to make sense in any mirror. That's because the compiler knows
- * the universe it's reifying an expression into (specified by the target of the `reify` call),
- * but it cannot know in advance the mirror to instantiate the result in (e.g. on JVM
- * it doesn't know what classloader use to resolve symbolic names in the reifee).
- *
- * Due to a typechecker restriction (no eta-expansion for dependent method types),
- * `TreeCreator` can't have a functional type, so it's implemented as class with an apply method.
+ * This class is used internally by Scala Reflection, and is not recommended for use in client code.
*/
abstract class TreeCreator {
def apply[U <: Universe with Singleton](m: scala.reflect.api.Mirror[U]): U # Tree
diff --git a/src/reflect/scala/reflect/api/Trees.scala b/src/reflect/scala/reflect/api/Trees.scala
index 5a87d1a90e..44f5776a57 100644
--- a/src/reflect/scala/reflect/api/Trees.scala
+++ b/src/reflect/scala/reflect/api/Trees.scala
@@ -5,67 +5,62 @@
package scala.reflect
package api
-// Syncnote: Trees are currently not thread-safe.
+/** This trait defines the node types used in Scala abstract syntax trees (AST) and operations on them.
+ *
+* All tree node types are sub types of [[scala.reflect.api.Trees#Tree Tree]].
+ *
+ * Trees are immutable, except for three fields
+ * [[Trees#TreeApi.pos pos]], [[Trees#TreeApi.symbol symbol]], and [[Trees#TreeApi.tpe tpe]], which are assigned when a tree is typechecked
+ * to attribute it with the information gathered by the typechecker.
+ *
+ * [[scala.reflect.api.Universe#reify reify]] can be used to get the tree for a given Scala expression.
+ *
+ * [[scala.reflect.api.Universe#showRaw showRaw]] can be used to get a readable representation of a tree.
+ *
+ * === Examples ===
+ * `Literal(Constant(5))` creates an AST representing a literal 5 in Scala source code.
+ *
+ * `Apply(Select(Select(This(newTypeName("scala")), newTermName("Predef")), newTermName("print")), List(Literal(Constant("Hello World"))))`
+ * creates an AST representing `print("Hello World")`.
+ *
+ * `import scala.reflect.runtime.universe.{reify,showRaw}`
+ * `print( showRaw( reify{5}.tree ) )` // prints Literal(Constant(5))
+ *
+ * @see [[http://docs.scala-lang.org/overviews/reflection/symbols-trees-types.html#trees]].
+ * @groupname Traversal Tree Traversal and Transformation
+ * @groupprio Traversal 1
+ * @groupprio Factories 1
+ * @groupname Copying Tree Copying
+ * @groupprio Copying 1
+ *
+ * @contentDiagram hideNodes "*Api"
+ */
trait Trees { self: Universe =>
- /** Tree is the basis for scala's abstract syntax. The nodes are
- * implemented as case classes, and the parameters which initialize
- * a given tree are immutable: however Trees have several mutable
- * fields which are manipulated in the course of typechecking,
- * including pos, symbol, and tpe.
- *
- * Newly instantiated trees have tpe set to null (though it
- * may be set immediately thereafter depending on how it is
- * constructed.) When a tree is passed to the typer, typically via
- * `typer.typed(tree)`, under normal circumstances the tpe must be
- * null or the typer will ignore it. Furthermore, the typer is not
- * required to return the same tree it was passed.
- *
- * Trees can be easily traversed with e.g. foreach on the root node;
- * for a more nuanced traversal, subclass Traverser. Transformations
- * can be considerably trickier: see the numerous subclasses of
- * Transformer found around the compiler.
- *
- * Copying Trees should be done with care depending on whether
- * it needs be done lazily or strictly (see LazyTreeCopier and
- * StrictTreeCopier) and on whether the contents of the mutable
- * fields should be copied. The tree copiers will copy the mutable
- * attributes to the new tree; calling Tree#duplicate will copy
- * symbol and tpe, but all the positions will be focused.
- *
- * Trees can be coarsely divided into four mutually exclusive categories:
- *
- * - TermTrees, representing terms
- * - TypTrees, representing types. Note that is `TypTree`, not `TypeTree`.
- * - SymTrees, which may represent types or terms.
- * - Other Trees, which have none of those as parents.
- *
- * SymTrees include important nodes Ident and Select, which are
- * used as both terms and types; they are distinguishable based on
- * whether the Name is a TermName or TypeName. The correct way
- * to test any Tree for a type or a term are the `isTerm`/`isType`
- * methods on Tree.
- *
- * "Others" are mostly syntactic or short-lived constructs. Examples
- * include CaseDef, which wraps individual match cases: they are
- * neither terms nor types, nor do they carry a symbol. Another
- * example is Parens, which is eliminated during parsing.
+ /** The type of Scala abstract syntax trees.
+ * @group Trees
+ * @template
*/
type Tree >: Null <: TreeApi
/** A tag that preserves the identity of the `Tree` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val TreeTag: ClassTag[Tree]
- /** The API that all trees support */
+ /** The API that all trees support.
+ * The main source of information about trees is the [[scala.reflect.api.Trees]] page.
+ * @group API
+ */
trait TreeApi extends Product { this: Tree =>
- // TODO
- /** ... */
+ /** Does this tree represent a definition? (of a method, of a class, etc) */
def isDef: Boolean
- // TODO
- /** ... */
+ /** Is this tree one of the empty trees?
+ * Empty trees are: the `EmptyTree` null object, `TypeTree` instances that don't carry a type
+ * and the special `emptyValDef` singleton.
+ */
def isEmpty: Boolean
/** The canonical way to test if a Tree represents a term.
@@ -76,26 +71,34 @@ trait Trees { self: Universe =>
*/
def isType: Boolean
- /** ... */
+ /** Position of the tree. */
def pos: Position
- /** ... */
+ /** Type of the tree.
+ *
+ * Upon creation most trees have their `tpe` set to `null`.
+ * Types are typically assigned to trees during typechecking.
+ * Some node factory methods set `tpe` immediately after creation.
+ *
+ * When the typechecker encounters a tree with a non-null tpe,
+ * it will assume it to be correct and not check it again. This means one has
+ * to be careful not to erase the `tpe` field of subtrees.
+ */
def tpe: Type
- /** Note that symbol is fixed as null at this level. In SymTrees,
- * it is overridden and implemented with a var, initialized to NoSymbol.
+ /** Symbol of the tree.
*
- * Trees which are not SymTrees but which carry symbols do so by
- * overriding `def symbol` to forward it elsewhere. Examples:
+ * For most trees symbol is `null`. In `SymTree`s,
+ * it is overridden and implemented with a var, initialized to `NoSymbol`.
*
- * Super(qual, _) // has qual's symbol
- * Apply(fun, args) // has fun's symbol
- * TypeApply(fun, args) // has fun's symbol
- * AppliedTypeTree(tpt, args) // has tpt's symbol
- * TypeTree(tpe) // has tpe's typeSymbol, if tpe != null
+ * Trees which are not `SymTree`s but which carry symbols do so by
+ * overriding `def symbol` to forward it elsewhere. Examples:
*
- * Attempting to set the symbol of a Tree which does not support
- * it will induce an exception.
+ * - `Super(qual, _)` has `qual`'s symbol,
+ * - `Apply(fun, args)` has `fun`'s symbol,
+ * - `TypeApply(fun, args)` has `fun`'s symbol,
+ * - `AppliedTypeTree(tpt, args)` has `tpt`'s symbol,
+ * - `TypeTree(tpe)` has `tpe`'s `typeSymbol`, if `tpe != null`.
*/
def symbol: Symbol
@@ -172,166 +175,239 @@ trait Trees { self: Universe =>
override def toString: String = treeToString(this)
}
- /** Obtains string representation of a tree */
+ /** Obtains string representation of a tree
+ * @group Trees
+ */
protected def treeToString(tree: Tree): String
- /** The empty tree */
+ /** The empty tree
+ * @group Trees
+ */
val EmptyTree: Tree
/** A tree for a term. Not all trees representing terms are TermTrees; use isTerm
* to reliably identify terms.
+ * @group Trees
+ * @template
*/
type TermTree >: Null <: AnyRef with Tree with TermTreeApi
/** A tag that preserves the identity of the `TermTree` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val TermTreeTag: ClassTag[TermTree]
- /** The API that all term trees support */
+ /** The API that all term trees support
+ * @group API
+ */
trait TermTreeApi extends TreeApi { this: TermTree =>
}
/** A tree for a type. Not all trees representing types are TypTrees; use isType
* to reliably identify types.
+ * @group Trees
+ * @template
*/
type TypTree >: Null <: AnyRef with Tree with TypTreeApi
/** A tag that preserves the identity of the `TypTree` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val TypTreeTag: ClassTag[TypTree]
- /** The API that all typ trees support */
+ /** The API that all typ trees support
+ * @group API
+ */
trait TypTreeApi extends TreeApi { this: TypTree =>
}
/** A tree with a mutable symbol field, initialized to NoSymbol.
+ * @group Trees
+ * @template
*/
type SymTree >: Null <: AnyRef with Tree with SymTreeApi
/** A tag that preserves the identity of the `SymTree` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val SymTreeTag: ClassTag[SymTree]
- /** The API that all sym trees support */
+ /** The API that all sym trees support
+ * @group API
+ */
trait SymTreeApi extends TreeApi { this: SymTree =>
+ /** @inheritdoc */
def symbol: Symbol
}
/** A tree with a name - effectively, a DefTree or RefTree.
+ * @group Trees
+ * @template
*/
type NameTree >: Null <: AnyRef with Tree with NameTreeApi
/** A tag that preserves the identity of the `NameTree` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val NameTreeTag: ClassTag[NameTree]
- /** The API that all name trees support */
+ /** The API that all name trees support
+ * @group API
+ */
trait NameTreeApi extends TreeApi { this: NameTree =>
+ /** The underlying name.
+ * For example, the `<List>` part of `Ident("List": TermName)`.
+ */
def name: Name
}
/** A tree which references a symbol-carrying entity.
* References one, as opposed to defining one; definitions
* are in DefTrees.
+ * @group Trees
+ * @template
*/
type RefTree >: Null <: SymTree with NameTree with RefTreeApi
/** A tag that preserves the identity of the `RefTree` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val RefTreeTag: ClassTag[RefTree]
- /** The API that all ref trees support */
+ /** The API that all ref trees support
+ * @group API
+ */
trait RefTreeApi extends SymTreeApi with NameTreeApi { this: RefTree =>
- def qualifier: Tree // empty for Idents
+ /** The qualifier of the reference.
+ * For example, the `<scala>` part of `Select("scala": TermName, "List": TermName)`.
+ * `EmptyTree` for `Ident` instances.
+ */
+ def qualifier: Tree
+
+ /** @inheritdoc */
def name: Name
}
/** A tree which defines a symbol-carrying entity.
+ * @group Trees
+ * @template
*/
type DefTree >: Null <: SymTree with NameTree with DefTreeApi
/** A tag that preserves the identity of the `DefTree` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val DefTreeTag: ClassTag[DefTree]
- /** The API that all def trees support */
+ /** The API that all def trees support
+ * @group API
+ */
trait DefTreeApi extends SymTreeApi with NameTreeApi { this: DefTree =>
+ /** @inheritdoc */
def name: Name
}
/** Common base class for all member definitions: types, classes,
* objects, packages, vals and vars, defs.
+ * @group Trees
+ * @template
*/
type MemberDef >: Null <: DefTree with MemberDefApi
/** A tag that preserves the identity of the `MemberDef` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val MemberDefTag: ClassTag[MemberDef]
- /** The API that all member defs support */
+ /** The API that all member defs support
+ * @group API
+ */
trait MemberDefApi extends DefTreeApi { this: MemberDef =>
+ /** Modifiers of the declared member. */
def mods: Modifiers
}
/** A packaging, such as `package pid { stats }`
+ * @group Trees
+ * @template
*/
type PackageDef >: Null <: MemberDef with PackageDefApi
/** A tag that preserves the identity of the `PackageDef` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val PackageDefTag: ClassTag[PackageDef]
- /** The constructor/deconstructor for `PackageDef` instances. */
+ /** The constructor/deconstructor for `PackageDef` instances.
+ * @group Extractors
+ */
val PackageDef: PackageDefExtractor
/** An extractor class to create and pattern match with syntax `PackageDef(pid, stats)`.
* This AST node corresponds to the following Scala code:
*
* `package` pid { stats }
+ * @group Extractors
*/
abstract class PackageDefExtractor {
def apply(pid: RefTree, stats: List[Tree]): PackageDef
def unapply(packageDef: PackageDef): Option[(RefTree, List[Tree])]
}
- /** The API that all package defs support */
+ /** The API that all package defs support
+ * @group API
+ */
trait PackageDefApi extends MemberDefApi { this: PackageDef =>
+ /** The (possibly, fully-qualified) name of the package. */
val pid: RefTree
+
+ /** Body of the package definition. */
val stats: List[Tree]
}
/** A common base class for class and object definitions.
+ * @group Trees
+ * @template
*/
type ImplDef >: Null <: MemberDef with ImplDefApi
/** A tag that preserves the identity of the `ImplDef` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val ImplDefTag: ClassTag[ImplDef]
- /** The API that all impl defs support */
+ /** The API that all impl defs support
+ * @group API
+ */
trait ImplDefApi extends MemberDefApi { this: ImplDef =>
+ /** The body of the definition. */
val impl: Template
}
/** A class definition.
+ * @group Trees
+ * @template
*/
type ClassDef >: Null <: ImplDef with ClassDefApi
/** A tag that preserves the identity of the `ClassDef` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val ClassDefTag: ClassTag[ClassDef]
- /** The constructor/deconstructor for `ClassDef` instances. */
+ /** The constructor/deconstructor for `ClassDef` instances.
+ * @group Extractors
+ */
val ClassDef: ClassDefExtractor
/** An extractor class to create and pattern match with syntax `ClassDef(mods, name, tparams, impl)`.
@@ -342,32 +418,47 @@ trait Trees { self: Universe =>
* Where impl stands for:
*
* `extends` parents { defs }
+ * @group Extractors
*/
abstract class ClassDefExtractor {
def apply(mods: Modifiers, name: TypeName, tparams: List[TypeDef], impl: Template): ClassDef
def unapply(classDef: ClassDef): Option[(Modifiers, TypeName, List[TypeDef], Template)]
}
- /** The API that all class defs support */
+ /** The API that all class defs support
+ * @group API
+ */
trait ClassDefApi extends ImplDefApi { this: ClassDef =>
+ /** @inheritdoc */
val mods: Modifiers
+
+ /** The name of the class. */
val name: TypeName
+
+ /** The type parameters of the class. */
val tparams: List[TypeDef]
+
+ /** @inheritdoc */
val impl: Template
}
/** An object definition, e.g. `object Foo`. Internally, objects are
* quite frequently called modules to reduce ambiguity.
* Eliminated by compiler phase refcheck.
+ * @group Trees
+ * @template
*/
type ModuleDef >: Null <: ImplDef with ModuleDefApi
/** A tag that preserves the identity of the `ModuleDef` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val ModuleDefTag: ClassTag[ModuleDef]
- /** The constructor/deconstructor for `ModuleDef` instances. */
+ /** The constructor/deconstructor for `ModuleDef` instances.
+ * @group Extractors
+ */
val ModuleDef: ModuleDefExtractor
/** An extractor class to create and pattern match with syntax `ModuleDef(mods, name, impl)`.
@@ -378,32 +469,55 @@ trait Trees { self: Universe =>
* Where impl stands for:
*
* `extends` parents { defs }
+ * @group Extractors
*/
abstract class ModuleDefExtractor {
def apply(mods: Modifiers, name: TermName, impl: Template): ModuleDef
def unapply(moduleDef: ModuleDef): Option[(Modifiers, TermName, Template)]
}
- /** The API that all module defs support */
+ /** The API that all module defs support
+ * @group API
+ */
trait ModuleDefApi extends ImplDefApi { this: ModuleDef =>
+ /** @inheritdoc */
val mods: Modifiers
+
+ /** The name of the module. */
val name: TermName
+
+ /** @inheritdoc */
val impl: Template
}
/** A common base class for ValDefs and DefDefs.
+ * @group Trees
+ * @template
*/
type ValOrDefDef >: Null <: MemberDef with ValOrDefDefApi
/** A tag that preserves the identity of the `ValOrDefDef` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val ValOrDefDefTag: ClassTag[ValOrDefDef]
- /** The API that all val defs and def defs support */
+ /** The API that all val defs and def defs support
+ * @group API
+ */
trait ValOrDefDefApi extends MemberDefApi { this: ValOrDefDef =>
+ /** @inheritdoc */
def name: Name // can't be a TermName because macros can be type names.
+
+ /** The type ascribed to the definition.
+ * An empty `TypeTree` if the type hasn't been specified explicitly
+ * and is supposed to be inferred.
+ */
def tpt: Tree
+
+ /** The body of the definition.
+ * The `EmptyTree` is the body is empty (e.g. for abstract members).
+ */
def rhs: Tree
}
@@ -414,15 +528,20 @@ trait Trees { self: Universe =>
* - lazy values, e.g. "lazy val x" - the LAZY flag set in mods
* - method parameters, see vparamss in [[scala.reflect.api.Trees#DefDef]] - the PARAM flag is set in mods
* - explicit self-types, e.g. class A { self: Bar => }
+ * @group Trees
+ * @template
*/
type ValDef >: Null <: ValOrDefDef with ValDefApi
/** A tag that preserves the identity of the `ValDef` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val ValDefTag: ClassTag[ValDef]
- /** The constructor/deconstructor for `ValDef` instances. */
+ /** The constructor/deconstructor for `ValDef` instances.
+ * @group Extractors
+ */
val ValDef: ValDefExtractor
/** An extractor class to create and pattern match with syntax `ValDef(mods, name, tpt, rhs)`.
@@ -438,31 +557,46 @@ trait Trees { self: Universe =>
*
* If the type of a value is not specified explicitly (i.e. is meant to be inferred),
* this is expressed by having `tpt` set to `TypeTree()` (but not to an `EmptyTree`!).
+ * @group Extractors
*/
abstract class ValDefExtractor {
def apply(mods: Modifiers, name: TermName, tpt: Tree, rhs: Tree): ValDef
def unapply(valDef: ValDef): Option[(Modifiers, TermName, Tree, Tree)]
}
- /** The API that all val defs support */
+ /** The API that all val defs support
+ * @group API
+ */
trait ValDefApi extends ValOrDefDefApi { this: ValDef =>
+ /** @inheritdoc */
val mods: Modifiers
+
+ /** @inheritdoc */
val name: TermName
+
+ /** @inheritdoc */
val tpt: Tree
+
+ /** @inheritdoc */
val rhs: Tree
}
/** A method or macro definition.
* @param name The name of the method or macro. Can be a type name in case this is a type macro
+ * @group Trees
+ * @template
*/
type DefDef >: Null <: ValOrDefDef with DefDefApi
/** A tag that preserves the identity of the `DefDef` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val DefDefTag: ClassTag[DefDef]
- /** The constructor/deconstructor for `DefDef` instances. */
+ /** The constructor/deconstructor for `DefDef` instances.
+ * @group Extractors
+ */
val DefDef: DefDefExtractor
/** An extractor class to create and pattern match with syntax `DefDef(mods, name, tparams, vparamss, tpt, rhs)`.
@@ -472,33 +606,52 @@ trait Trees { self: Universe =>
*
* If the return type is not specified explicitly (i.e. is meant to be inferred),
* this is expressed by having `tpt` set to `TypeTree()` (but not to an `EmptyTree`!).
+ * @group Extractors
*/
abstract class DefDefExtractor {
def apply(mods: Modifiers, name: Name, tparams: List[TypeDef], vparamss: List[List[ValDef]], tpt: Tree, rhs: Tree): DefDef
def unapply(defDef: DefDef): Option[(Modifiers, Name, List[TypeDef], List[List[ValDef]], Tree, Tree)]
}
- /** The API that all def defs support */
+ /** The API that all def defs support
+ * @group API
+ */
trait DefDefApi extends ValOrDefDefApi { this: DefDef =>
+ /** @inheritdoc */
val mods: Modifiers
+
+ /** @inheritdoc */
val name: Name
+
+ /** The type parameters of the method. */
val tparams: List[TypeDef]
+
+ /** The parameter lists of the method. */
val vparamss: List[List[ValDef]]
+
+ /** @inheritdoc */
val tpt: Tree
+
+ /** @inheritdoc */
val rhs: Tree
}
/** An abstract type, a type parameter, or a type alias.
* Eliminated by erasure.
+ * @group Trees
+ * @template
*/
type TypeDef >: Null <: MemberDef with TypeDefApi
/** A tag that preserves the identity of the `TypeDef` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val TypeDefTag: ClassTag[TypeDef]
- /** The constructor/deconstructor for `TypeDef` instances. */
+ /** The constructor/deconstructor for `TypeDef` instances.
+ * @group Extractors
+ */
val TypeDef: TypeDefExtractor
/** An extractor class to create and pattern match with syntax `TypeDef(mods, name, tparams, rhs)`.
@@ -511,17 +664,29 @@ trait Trees { self: Universe =>
* First usage illustrates `TypeDefs` representing type aliases and type parameters.
* Second usage illustrates `TypeDefs` representing abstract types,
* where lo and hi are both `TypeBoundsTrees` and `Modifier.deferred` is set in mods.
+ * @group Extractors
*/
abstract class TypeDefExtractor {
def apply(mods: Modifiers, name: TypeName, tparams: List[TypeDef], rhs: Tree): TypeDef
def unapply(typeDef: TypeDef): Option[(Modifiers, TypeName, List[TypeDef], Tree)]
}
- /** The API that all type defs support */
+ /** The API that all type defs support
+ * @group API
+ */
trait TypeDefApi extends MemberDefApi { this: TypeDef =>
+ /** @inheritdoc */
val mods: Modifiers
+
+ /** @inheritdoc */
val name: TypeName
+
+ /** The type parameters of this type definition. */
val tparams: List[TypeDef]
+
+ /** The body of the definition.
+ * The `EmptyTree` is the body is empty (e.g. for abstract type members).
+ */
val rhs: Tree
}
@@ -538,15 +703,20 @@ trait Trees { self: Universe =>
* assigned to the Idents.
*
* Forward jumps within a block are allowed.
+ * @group Trees
+ * @template
*/
type LabelDef >: Null <: DefTree with TermTree with LabelDefApi
/** A tag that preserves the identity of the `LabelDef` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val LabelDefTag: ClassTag[LabelDef]
- /** The constructor/deconstructor for `LabelDef` instances. */
+ /** The constructor/deconstructor for `LabelDef` instances.
+ * @group Extractors
+ */
val LabelDef: LabelDefExtractor
/** An extractor class to create and pattern match with syntax `LabelDef(name, params, rhs)`.
@@ -555,21 +725,33 @@ trait Trees { self: Universe =>
* It is used for tailcalls and like.
* For example, while/do are desugared to label defs as follows:
* {{{
- * while (cond) body ==> LabelDef($L, List(), if (cond) { body; L$() } else ())
+ * while (cond) body ==> LabelDef(\$L, List(), if (cond) { body; L\$() } else ())
* }}}
* {{{
- * do body while (cond) ==> LabelDef($L, List(), body; if (cond) L$() else ())
+ * do body while (cond) ==> LabelDef(\$L, List(), body; if (cond) L\$() else ())
* }}}
+ * @group Extractors
*/
abstract class LabelDefExtractor {
def apply(name: TermName, params: List[Ident], rhs: Tree): LabelDef
def unapply(labelDef: LabelDef): Option[(TermName, List[Ident], Tree)]
}
- /** The API that all label defs support */
+ /** The API that all label defs support
+ * @group API
+ */
trait LabelDefApi extends DefTreeApi with TermTreeApi { this: LabelDef =>
+ /** @inheritdoc */
val name: TermName
+
+ /** Label's parameters - names that can be used in the body of the label.
+ * See the example for [[scala.reflect.api.Trees#LabelDefExtractor]].
+ */
val params: List[Ident]
+
+ /** The body of the label.
+ * See the example for [[scala.reflect.api.Trees#LabelDefExtractor]].
+ */
val rhs: Tree
}
@@ -583,30 +765,51 @@ trait Trees { self: Universe =>
* @param namePos its position or -1 if undefined
* @param rename the name the import is renamed to (== name if no renaming)
* @param renamePos the position of the rename or -1 if undefined
+ * @group Trees
+ * @template
*/
type ImportSelector >: Null <: AnyRef with ImportSelectorApi
/** A tag that preserves the identity of the `ImportSelector` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val ImportSelectorTag: ClassTag[ImportSelector]
- /** The constructor/deconstructor for `ImportSelector` instances. */
+ /** The constructor/deconstructor for `ImportSelector` instances.
+ * @group Extractors
+ */
val ImportSelector: ImportSelectorExtractor
/** An extractor class to create and pattern match with syntax `ImportSelector(name:, namePos, rename, renamePos)`.
* This is not an AST node, it is used as a part of the `Import` node.
+ * @group Extractors
*/
abstract class ImportSelectorExtractor {
def apply(name: Name, namePos: Int, rename: Name, renamePos: Int): ImportSelector
def unapply(importSelector: ImportSelector): Option[(Name, Int, Name, Int)]
}
- /** The API that all import selectors support */
+ /** The API that all import selectors support
+ * @group API
+ */
trait ImportSelectorApi { this: ImportSelector =>
+ /** The imported name. */
val name: Name
+
+ /** Offset of the position of the importing part of the selector in the source file.
+ * Is equal to -1 is the position is unknown.
+ */
val namePos: Int
+
+ /** The name the import is renamed to.
+ * Is equal to `name` if it's not a renaming import.
+ */
val rename: Name
+
+ /** Offset of the position of the renaming part of the selector in the source file.
+ * Is equal to -1 is the position is unknown.
+ */
val renamePos: Int
}
@@ -614,15 +817,20 @@ trait Trees { self: Universe =>
*
* @param expr
* @param selectors
+ * @group Trees
+ * @template
*/
type Import >: Null <: SymTree with ImportApi
/** A tag that preserves the identity of the `Import` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val ImportTag: ClassTag[Import]
- /** The constructor/deconstructor for `Import` instances. */
+ /** The constructor/deconstructor for `Import` instances.
+ * @group Extractors
+ */
val Import: ImportExtractor
/** An extractor class to create and pattern match with syntax `Import(expr, selectors)`.
@@ -641,15 +849,25 @@ trait Trees { self: Universe =>
*
* The symbol of an `Import` is an import symbol @see Symbol.newImport.
* It's used primarily as a marker to check that the import has been typechecked.
+ * @group Extractors
*/
abstract class ImportExtractor {
def apply(expr: Tree, selectors: List[ImportSelector]): Import
def unapply(import_ : Import): Option[(Tree, List[ImportSelector])]
}
- /** The API that all imports support */
+ /** The API that all imports support
+ * @group API
+ */
trait ImportApi extends SymTreeApi { this: Import =>
+ /** The qualifier of the import.
+ * See the example for [[scala.reflect.api.Trees#ImportExtractor]].
+ */
val expr: Tree
+
+ /** The selectors of the import.
+ * See the example for [[scala.reflect.api.Trees#ImportExtractor]].
+ */
val selectors: List[ImportSelector]
}
@@ -657,15 +875,20 @@ trait Trees { self: Universe =>
*
* @param parents
* @param body
+ * @group Trees
+ * @template
*/
type Template >: Null <: SymTree with TemplateApi
/** A tag that preserves the identity of the `Template` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val TemplateTag: ClassTag[Template]
- /** The constructor/deconstructor for `Template` instances. */
+ /** The constructor/deconstructor for `Template` instances.
+ * @group Extractors
+ */
val Template: TemplateExtractor
/** An extractor class to create and pattern match with syntax `Template(parents, self, body)`.
@@ -685,28 +908,45 @@ trait Trees { self: Universe =>
* def bar // owner is local dummy
* }
* }
+ * @group Extractors
*/
abstract class TemplateExtractor {
def apply(parents: List[Tree], self: ValDef, body: List[Tree]): Template
def unapply(template: Template): Option[(List[Tree], ValDef, List[Tree])]
}
- /** The API that all templates support */
+ /** The API that all templates support
+ * @group API
+ */
trait TemplateApi extends SymTreeApi { this: Template =>
+ /** Superclasses of the template. */
val parents: List[Tree]
+
+ /** Self type of the template.
+ * Is equal to `emptyValDef` if the self type is not specified.
+ */
val self: ValDef
+
+ /** Body of the template.
+ */
val body: List[Tree]
}
- /** Block of expressions (semicolon separated expressions) */
+ /** Block of expressions (semicolon separated expressions)
+ * @group Trees
+ * @template
+ */
type Block >: Null <: TermTree with BlockApi
/** A tag that preserves the identity of the `Block` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val BlockTag: ClassTag[Block]
- /** The constructor/deconstructor for `Block` instances. */
+ /** The constructor/deconstructor for `Block` instances.
+ * @group Extractors
+ */
val Block: BlockExtractor
/** An extractor class to create and pattern match with syntax `Block(stats, expr)`.
@@ -715,30 +955,43 @@ trait Trees { self: Universe =>
* { stats; expr }
*
* If the block is empty, the `expr` is set to `Literal(Constant(()))`.
+ * @group Extractors
*/
abstract class BlockExtractor {
def apply(stats: List[Tree], expr: Tree): Block
def unapply(block: Block): Option[(List[Tree], Tree)]
}
- /** The API that all blocks support */
+ /** The API that all blocks support
+ * @group API
+ */
trait BlockApi extends TermTreeApi { this: Block =>
+ /** All, but the last, expressions in the block.
+ * Can very well be an empty list.
+ */
val stats: List[Tree]
+
+ /** The last expression in the block. */
val expr: Tree
}
/** Case clause in a pattern match.
* (except for occurrences in switch statements).
* Eliminated by compiler phases patmat (in the new pattern matcher of 2.10) or explicitouter (in the old pre-2.10 pattern matcher)
+ * @group Trees
+ * @template
*/
type CaseDef >: Null <: AnyRef with Tree with CaseDefApi
/** A tag that preserves the identity of the `CaseDef` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val CaseDefTag: ClassTag[CaseDef]
- /** The constructor/deconstructor for `CaseDef` instances. */
+ /** The constructor/deconstructor for `CaseDef` instances.
+ * @group Extractors
+ */
val CaseDef: CaseDefExtractor
/** An extractor class to create and pattern match with syntax `CaseDef(pat, guard, body)`.
@@ -748,16 +1001,28 @@ trait Trees { self: Universe =>
*
* If the guard is not present, the `guard` is set to `EmptyTree`.
* If the body is not specified, the `body` is set to `Literal(Constant())`
+ * @group Extractors
*/
abstract class CaseDefExtractor {
def apply(pat: Tree, guard: Tree, body: Tree): CaseDef
def unapply(caseDef: CaseDef): Option[(Tree, Tree, Tree)]
}
- /** The API that all case defs support */
+ /** The API that all case defs support
+ * @group API
+ */
trait CaseDefApi extends TreeApi { this: CaseDef =>
+ /** The pattern of the pattern matching clause. */
val pat: Tree
+
+ /** The guard of the pattern matching clause.
+ * Is equal to `EmptyTree` if the guard is not specified.
+ */
val guard: Tree
+
+ /** The body of the pattern matching clause.
+ * Is equal to `Literal(Constant())` if the body is not specified.
+ */
val body: Tree
}
@@ -766,58 +1031,76 @@ trait Trees { self: Universe =>
* Eliminated by compiler phases Eliminated by compiler phases patmat (in the new pattern matcher of 2.10) or explicitouter (in the old pre-2.10 pattern matcher),
* except for
* occurrences in encoded Switch stmt (i.e. remaining Match(CaseDef(...)))
+ * @group Trees
+ * @template
*/
type Alternative >: Null <: TermTree with AlternativeApi
/** A tag that preserves the identity of the `Alternative` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val AlternativeTag: ClassTag[Alternative]
- /** The constructor/deconstructor for `Alternative` instances. */
+ /** The constructor/deconstructor for `Alternative` instances.
+ * @group Extractors
+ */
val Alternative: AlternativeExtractor
/** An extractor class to create and pattern match with syntax `Alternative(trees)`.
* This AST node corresponds to the following Scala code:
*
* pat1 | ... | patn
+ * @group Extractors
*/
abstract class AlternativeExtractor {
def apply(trees: List[Tree]): Alternative
def unapply(alternative: Alternative): Option[List[Tree]]
}
- /** The API that all alternatives support */
+ /** The API that all alternatives support
+ * @group API
+ */
trait AlternativeApi extends TermTreeApi { this: Alternative =>
+ /** Alternatives of the pattern matching clause. */
val trees: List[Tree]
}
/** Repetition of pattern.
*
* Eliminated by compiler phases patmat (in the new pattern matcher of 2.10) or explicitouter (in the old pre-2.10 pattern matcher).
+ * @group Trees
+ * @template
*/
type Star >: Null <: TermTree with StarApi
/** A tag that preserves the identity of the `Star` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val StarTag: ClassTag[Star]
- /** The constructor/deconstructor for `Star` instances. */
+ /** The constructor/deconstructor for `Star` instances.
+ * @group Extractors
+ */
val Star: StarExtractor
/** An extractor class to create and pattern match with syntax `Star(elem)`.
* This AST node corresponds to the following Scala code:
*
* pat*
+ * @group Extractors
*/
abstract class StarExtractor {
def apply(elem: Tree): Star
def unapply(star: Star): Option[Tree]
}
- /** The API that all stars support */
+ /** The API that all stars support
+ * @group API
+ */
trait StarApi extends TermTreeApi { this: Star =>
+ /** The quantified pattern. */
val elem: Tree
}
@@ -827,30 +1110,46 @@ trait Trees { self: Universe =>
*
* @param name
* @param body
+ * @group Trees
+ * @template
*/
type Bind >: Null <: DefTree with BindApi
/** A tag that preserves the identity of the `Bind` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val BindTag: ClassTag[Bind]
- /** The constructor/deconstructor for `Bind` instances. */
+ /** The constructor/deconstructor for `Bind` instances.
+ * @group Extractors
+ */
val Bind: BindExtractor
/** An extractor class to create and pattern match with syntax `Bind(name, body)`.
* This AST node corresponds to the following Scala code:
*
* pat*
+ * @group Extractors
*/
abstract class BindExtractor {
def apply(name: Name, body: Tree): Bind
def unapply(bind: Bind): Option[(Name, Tree)]
}
- /** The API that all binds support */
+ /** The API that all binds support
+ * @group API
+ */
trait BindApi extends DefTreeApi { this: Bind =>
+ /** The name that can be used to refer to this fragment of the matched expression.
+ * The `list` part of the `list @ List(x, y)`.
+ */
val name: Name
+
+ /** The pattern that represents this fragment of the matched expression.
+ * The `List(x, y)` part of the `list @ List(x, y)`.
+ * Is equal to `EmptyTree` if the pattern is not specified as in `case x => x`.
+ */
val body: Tree
}
@@ -880,41 +1179,62 @@ trait Trees { self: Universe =>
* }}}
*
* Introduced by typer. Eliminated by compiler phases patmat (in the new pattern matcher of 2.10) or explicitouter (in the old pre-2.10 pattern matcher).
+ * @group Trees
+ * @template
*/
type UnApply >: Null <: TermTree with UnApplyApi
/** A tag that preserves the identity of the `UnApply` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val UnApplyTag: ClassTag[UnApply]
- /** The constructor/deconstructor for `UnApply` instances. */
+ /** The constructor/deconstructor for `UnApply` instances.
+ * @group Extractors
+ */
val UnApply: UnApplyExtractor
/** An extractor class to create and pattern match with syntax `UnApply(fun, args)`.
* This AST node does not have direct correspondence to Scala code,
* and is introduced when typechecking pattern matches and `try` blocks.
+ * @group Extractors
*/
abstract class UnApplyExtractor {
def apply(fun: Tree, args: List[Tree]): UnApply
def unapply(unApply: UnApply): Option[(Tree, List[Tree])]
}
- /** The API that all unapplies support */
+ /** The API that all unapplies support
+ * @group API
+ */
trait UnApplyApi extends TermTreeApi { this: UnApply =>
+ /** A dummy node that carries the type of unapplication.
+ * See the example for [[scala.reflect.api.Trees#UnApplyExtractor]].
+ */
val fun: Tree
+
+ /** The arguments of the unapplication.
+ * See the example for [[scala.reflect.api.Trees#UnApplyExtractor]].
+ */
val args: List[Tree]
}
- /** Anonymous function, eliminated by compiler phase lambdalift */
+ /** Anonymous function, eliminated by compiler phase lambdalift
+ * @group Trees
+ * @template
+ */
type Function >: Null <: TermTree with SymTree with FunctionApi
/** A tag that preserves the identity of the `Function` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val FunctionTag: ClassTag[Function]
- /** The constructor/deconstructor for `Function` instances. */
+ /** The constructor/deconstructor for `Function` instances.
+ * @group Extractors
+ */
val Function: FunctionExtractor
/** An extractor class to create and pattern match with syntax `Function(vparams, body)`.
@@ -924,56 +1244,83 @@ trait Trees { self: Universe =>
*
* The symbol of a Function is a synthetic TermSymbol.
* It is the owner of the function's parameters.
+ * @group Extractors
*/
abstract class FunctionExtractor {
def apply(vparams: List[ValDef], body: Tree): Function
def unapply(function: Function): Option[(List[ValDef], Tree)]
}
- /** The API that all functions support */
+ /** The API that all functions support
+ * @group API
+ */
trait FunctionApi extends TermTreeApi with SymTreeApi { this: Function =>
+ /** The list of parameters of the function.
+ */
val vparams: List[ValDef]
+
+ /** The body of the function.
+ */
val body: Tree
}
- /** Assignment */
+ /** Assignment
+ * @group Trees
+ * @template
+ */
type Assign >: Null <: TermTree with AssignApi
/** A tag that preserves the identity of the `Assign` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val AssignTag: ClassTag[Assign]
- /** The constructor/deconstructor for `Assign` instances. */
+ /** The constructor/deconstructor for `Assign` instances.
+ * @group Extractors
+ */
val Assign: AssignExtractor
/** An extractor class to create and pattern match with syntax `Assign(lhs, rhs)`.
* This AST node corresponds to the following Scala code:
*
* lhs = rhs
+ * @group Extractors
*/
abstract class AssignExtractor {
def apply(lhs: Tree, rhs: Tree): Assign
def unapply(assign: Assign): Option[(Tree, Tree)]
}
- /** The API that all assigns support */
+ /** The API that all assigns support
+ * @group API
+ */
trait AssignApi extends TermTreeApi { this: Assign =>
+ /** The left-hand side of the assignment.
+ */
val lhs: Tree
+
+ /** The right-hand side of the assignment.
+ */
val rhs: Tree
}
/** Either an assignment or a named argument. Only appears in argument lists,
* eliminated by compiler phase typecheck (doTypedApply), resurrected by reifier.
+ * @group Trees
+ * @template
*/
type AssignOrNamedArg >: Null <: TermTree with AssignOrNamedArgApi
/** A tag that preserves the identity of the `AssignOrNamedArg` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val AssignOrNamedArgTag: ClassTag[AssignOrNamedArg]
- /** The constructor/deconstructor for `AssignOrNamedArg` instances. */
+ /** The constructor/deconstructor for `AssignOrNamedArg` instances.
+ * @group Extractors
+ */
val AssignOrNamedArg: AssignOrNamedArgExtractor
/** An extractor class to create and pattern match with syntax `AssignOrNamedArg(lhs, rhs)`.
@@ -986,27 +1333,41 @@ trait Trees { self: Universe =>
* @annotation(lhs = rhs)
* }}}
*
+ * @group Extractors
*/
abstract class AssignOrNamedArgExtractor {
def apply(lhs: Tree, rhs: Tree): AssignOrNamedArg
def unapply(assignOrNamedArg: AssignOrNamedArg): Option[(Tree, Tree)]
}
- /** The API that all assigns support */
+ /** The API that all assigns support
+ * @group API
+ */
trait AssignOrNamedArgApi extends TermTreeApi { this: AssignOrNamedArg =>
+ /** The left-hand side of the expression.
+ */
val lhs: Tree
+
+ /** The right-hand side of the expression.
+ */
val rhs: Tree
}
- /** Conditional expression */
+ /** Conditional expression
+ * @group Trees
+ * @template
+ */
type If >: Null <: TermTree with IfApi
/** A tag that preserves the identity of the `If` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val IfTag: ClassTag[If]
- /** The constructor/deconstructor for `If` instances. */
+ /** The constructor/deconstructor for `If` instances.
+ * @group Extractors
+ */
val If: IfExtractor
/** An extractor class to create and pattern match with syntax `If(cond, thenp, elsep)`.
@@ -1015,16 +1376,28 @@ trait Trees { self: Universe =>
* `if` (cond) thenp `else` elsep
*
* If the alternative is not present, the `elsep` is set to `Literal(Constant(()))`.
+ * @group Extractors
*/
abstract class IfExtractor {
def apply(cond: Tree, thenp: Tree, elsep: Tree): If
def unapply(if_ : If): Option[(Tree, Tree, Tree)]
}
- /** The API that all ifs support */
+ /** The API that all ifs support
+ * @group API
+ */
trait IfApi extends TermTreeApi { this: If =>
+ /** The condition of the if.
+ */
val cond: Tree
+
+ /** The main branch of the if.
+ */
val thenp: Tree
+
+ /** The alternative of the if.
+ * Is equal to `Literal(Constant(()))` if not specified.
+ */
val elsep: Tree
}
@@ -1038,15 +1411,20 @@ trait Trees { self: Universe =>
* or `Alternative(lit|...|lit)`
* - except for an "otherwise" branch, which has pattern
* `Ident(nme.WILDCARD)`
+ * @group Trees
+ * @template
*/
type Match >: Null <: TermTree with MatchApi
/** A tag that preserves the identity of the `Match` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val MatchTag: ClassTag[Match]
- /** The constructor/deconstructor for `Match` instances. */
+ /** The constructor/deconstructor for `Match` instances.
+ * @group Extractors
+ */
val Match: MatchExtractor
/** An extractor class to create and pattern match with syntax `Match(selector, cases)`.
@@ -1055,27 +1433,39 @@ trait Trees { self: Universe =>
* selector `match` { cases }
*
* `Match` is also used in pattern matching assignments like `val (foo, bar) = baz`.
+ * @group Extractors
*/
abstract class MatchExtractor {
def apply(selector: Tree, cases: List[CaseDef]): Match
def unapply(match_ : Match): Option[(Tree, List[CaseDef])]
}
- /** The API that all matches support */
+ /** The API that all matches support
+ * @group API
+ */
trait MatchApi extends TermTreeApi { this: Match =>
+ /** The scrutinee of the pattern match. */
val selector: Tree
+
+ /** The arms of the pattern match. */
val cases: List[CaseDef]
}
- /** Return expression */
+ /** Return expression
+ * @group Trees
+ * @template
+ */
type Return >: Null <: TermTree with SymTree with ReturnApi
/** A tag that preserves the identity of the `Return` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val ReturnTag: ClassTag[Return]
- /** The constructor/deconstructor for `Return` instances. */
+ /** The constructor/deconstructor for `Return` instances.
+ * @group Extractors
+ */
val Return: ReturnExtractor
/** An extractor class to create and pattern match with syntax `Return(expr)`.
@@ -1084,26 +1474,36 @@ trait Trees { self: Universe =>
* `return` expr
*
* The symbol of a Return node is the enclosing method.
+ * @group Extractors
*/
abstract class ReturnExtractor {
def apply(expr: Tree): Return
def unapply(return_ : Return): Option[Tree]
}
- /** The API that all returns support */
+ /** The API that all returns support
+ * @group API
+ */
trait ReturnApi extends TermTreeApi { this: Return =>
+ /** The returned expression. */
val expr: Tree
}
- /** [Eugene++] comment me! */
+ /** Try catch node
+ * @group Trees
+ * @template
+ */
type Try >: Null <: TermTree with TryApi
/** A tag that preserves the identity of the `Try` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val TryTag: ClassTag[Try]
- /** The constructor/deconstructor for `Try` instances. */
+ /** The constructor/deconstructor for `Try` instances.
+ * @group Extractors
+ */
val Try: TryExtractor
/** An extractor class to create and pattern match with syntax `Try(block, catches, finalizer)`.
@@ -1112,55 +1512,77 @@ trait Trees { self: Universe =>
* `try` block `catch` { catches } `finally` finalizer
*
* If the finalizer is not present, the `finalizer` is set to `EmptyTree`.
+ * @group Extractors
*/
abstract class TryExtractor {
def apply(block: Tree, catches: List[CaseDef], finalizer: Tree): Try
def unapply(try_ : Try): Option[(Tree, List[CaseDef], Tree)]
}
- /** The API that all tries support */
+ /** The API that all tries support
+ * @group API
+ */
trait TryApi extends TermTreeApi { this: Try =>
+ /** The protected block. */
val block: Tree
+
+ /** The `catch` pattern-matching clauses of the try. */
val catches: List[CaseDef]
+
+ /** The `finally` part of the try. */
val finalizer: Tree
}
- /** Throw expression */
+ /** Throw expression
+ * @group Trees
+ * @template
+ */
type Throw >: Null <: TermTree with ThrowApi
/** A tag that preserves the identity of the `Throw` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val ThrowTag: ClassTag[Throw]
- /** The constructor/deconstructor for `Throw` instances. */
+ /** The constructor/deconstructor for `Throw` instances.
+ * @group Extractors
+ */
val Throw: ThrowExtractor
/** An extractor class to create and pattern match with syntax `Throw(expr)`.
* This AST node corresponds to the following Scala code:
*
* `throw` expr
+ * @group Extractors
*/
abstract class ThrowExtractor {
def apply(expr: Tree): Throw
def unapply(throw_ : Throw): Option[Tree]
}
- /** The API that all tries support */
+ /** The API that all tries support
+ * @group API
+ */
trait ThrowApi extends TermTreeApi { this: Throw =>
+ /** The thrown expression. */
val expr: Tree
}
/** Object instantiation
+ * @group Trees
+ * @template
*/
type New >: Null <: TermTree with NewApi
/** A tag that preserves the identity of the `New` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val NewTag: ClassTag[New]
/** The constructor/deconstructor for `New` instances.
+ * @group Extractors
*/
val New: NewExtractor
@@ -1172,6 +1594,7 @@ trait Trees { self: Universe =>
* This node always occurs in the following context:
*
* (`new` tpt).<init>[targs](args)
+ * @group Extractors
*/
abstract class NewExtractor {
/** A user level `new`.
@@ -1183,50 +1606,75 @@ trait Trees { self: Universe =>
def unapply(new_ : New): Option[Tree]
}
- /** The API that all news support */
+ /** The API that all news support
+ * @group API
+ */
trait NewApi extends TermTreeApi { this: New =>
+ /** The tree that represents the type being instantiated.
+ * See the example for [[scala.reflect.api.Trees#NewExtractor]].
+ */
val tpt: Tree
}
- /** Type annotation, eliminated by compiler phase cleanup */
+ /** Type annotation, eliminated by compiler phase cleanup
+ * @group Trees
+ * @template
+ */
type Typed >: Null <: TermTree with TypedApi
/** A tag that preserves the identity of the `Typed` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val TypedTag: ClassTag[Typed]
- /** The constructor/deconstructor for `Typed` instances. */
+ /** The constructor/deconstructor for `Typed` instances.
+ * @group Extractors
+ */
val Typed: TypedExtractor
/** An extractor class to create and pattern match with syntax `Typed(expr, tpt)`.
* This AST node corresponds to the following Scala code:
*
* expr: tpt
+ * @group Extractors
*/
abstract class TypedExtractor {
def apply(expr: Tree, tpt: Tree): Typed
def unapply(typed: Typed): Option[(Tree, Tree)]
}
- /** The API that all typeds support */
+ /** The API that all typeds support
+ * @group API
+ */
trait TypedApi extends TermTreeApi { this: Typed =>
+ /** The expression being ascribed with the type. */
val expr: Tree
+
+ /** The type being ascribed to the expression. */
val tpt: Tree
}
/** Common base class for Apply and TypeApply.
+ * @group Trees
+ * @template
*/
type GenericApply >: Null <: TermTree with GenericApplyApi
/** A tag that preserves the identity of the `GenericApply` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val GenericApplyTag: ClassTag[GenericApply]
- /** The API that all applies support */
+ /** The API that all applies support
+ * @group API
+ */
trait GenericApplyApi extends TermTreeApi { this: GenericApply =>
+ /** The target of the application. */
val fun: Tree
+
+ /** The arguments of the application. */
val args: List[Tree]
}
@@ -1234,40 +1682,55 @@ trait Trees { self: Universe =>
* but I can't find that explicitly stated anywhere. Unless your last name
* is odersky, you should probably treat it as true.
*/
- /** Explicit type application. */
+ /** Explicit type application.
+ * @group Trees
+ * @template
+ */
type TypeApply >: Null <: GenericApply with TypeApplyApi
/** A tag that preserves the identity of the `TypeApply` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val TypeApplyTag: ClassTag[TypeApply]
- /** The constructor/deconstructor for `TypeApply` instances. */
+ /** The constructor/deconstructor for `TypeApply` instances.
+ * @group Extractors
+ */
val TypeApply: TypeApplyExtractor
/** An extractor class to create and pattern match with syntax `TypeApply(fun, args)`.
* This AST node corresponds to the following Scala code:
*
* fun[args]
+ * @group Extractors
*/
abstract class TypeApplyExtractor {
def apply(fun: Tree, args: List[Tree]): TypeApply
def unapply(typeApply: TypeApply): Option[(Tree, List[Tree])]
}
- /** The API that all type applies support */
+ /** The API that all type applies support
+ * @group API
+ */
trait TypeApplyApi extends GenericApplyApi { this: TypeApply =>
}
- /** Value application */
+ /** Value application
+ * @group Trees
+ * @template
+ */
type Apply >: Null <: GenericApply with ApplyApi
/** A tag that preserves the identity of the `Apply` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val ApplyTag: ClassTag[Apply]
- /** The constructor/deconstructor for `Apply` instances. */
+ /** The constructor/deconstructor for `Apply` instances.
+ * @group Extractors
+ */
val Apply: ApplyExtractor
/** An extractor class to create and pattern match with syntax `Apply(fun, args)`.
@@ -1282,27 +1745,35 @@ trait Trees { self: Universe =>
* Is expressed as:
*
* Apply(TypeApply(fun, targs), args)
+ * @group Extractors
*/
abstract class ApplyExtractor {
def apply(fun: Tree, args: List[Tree]): Apply
def unapply(apply: Apply): Option[(Tree, List[Tree])]
}
- /** The API that all applies support */
+ /** The API that all applies support
+ * @group API
+ */
trait ApplyApi extends GenericApplyApi { this: Apply =>
}
/** Super reference, where `qual` is the corresponding `this` reference.
* A super reference `C.super[M]` is represented as `Super(This(C), M)`.
+ * @group Trees
+ * @template
*/
type Super >: Null <: TermTree with SuperApi
/** A tag that preserves the identity of the `Super` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val SuperTag: ClassTag[Super]
- /** The constructor/deconstructor for `Super` instances. */
+ /** The constructor/deconstructor for `Super` instances.
+ * @group Extractors
+ */
val Super: SuperExtractor
/** An extractor class to create and pattern match with syntax `Super(qual, mix)`.
@@ -1318,27 +1789,43 @@ trait Trees { self: Universe =>
*
* The symbol of a Super is the class _from_ which the super reference is made.
* For instance in C.super(...), it would be C.
+ * @group Extractors
*/
abstract class SuperExtractor {
def apply(qual: Tree, mix: TypeName): Super
def unapply(super_ : Super): Option[(Tree, TypeName)]
}
- /** The API that all supers support */
+ /** The API that all supers support
+ * @group API
+ */
trait SuperApi extends TermTreeApi { this: Super =>
+ /** The qualifier of the `super` expression.
+ * See the example for [[scala.reflect.api.Trees#SuperExtractor]].
+ */
val qual: Tree
+
+ /** The selector of the `super` expression.
+ * See the example for [[scala.reflect.api.Trees#SuperExtractor]].
+ */
val mix: TypeName
}
- /** Self reference */
+ /** Self reference
+ * @group Trees
+ * @template
+ */
type This >: Null <: TermTree with SymTree with ThisApi
/** A tag that preserves the identity of the `This` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val ThisTag: ClassTag[This]
- /** The constructor/deconstructor for `This` instances. */
+ /** The constructor/deconstructor for `This` instances.
+ * @group Extractors
+ */
val This: ThisExtractor
/** An extractor class to create and pattern match with syntax `This(qual)`.
@@ -1348,55 +1835,77 @@ trait Trees { self: Universe =>
*
* The symbol of a This is the class to which the this refers.
* For instance in C.this, it would be C.
- *
- * If `mix` is empty, then ???
+ * @group Extractors
*/
abstract class ThisExtractor {
def apply(qual: TypeName): This
def unapply(this_ : This): Option[TypeName]
}
- /** The API that all thises support */
+ /** The API that all thises support
+ * @group API
+ */
trait ThisApi extends TermTreeApi with SymTreeApi { this: This =>
+ /** The qualifier of the `this` expression.
+ * For an unqualified `this` refers to the enclosing class.
+ */
val qual: TypeName
}
- /** Designator <qualifier> . <name> */
+ /** A member selection <qualifier> . <name>
+ * @group Trees
+ * @template
+ */
type Select >: Null <: RefTree with SelectApi
/** A tag that preserves the identity of the `Select` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val SelectTag: ClassTag[Select]
- /** The constructor/deconstructor for `Select` instances. */
+ /** The constructor/deconstructor for `Select` instances.
+ * @group Extractors
+ */
val Select: SelectExtractor
/** An extractor class to create and pattern match with syntax `Select(qual, name)`.
* This AST node corresponds to the following Scala code:
*
* qualifier.selector
+ * @group Extractors
*/
abstract class SelectExtractor {
def apply(qualifier: Tree, name: Name): Select
def unapply(select: Select): Option[(Tree, Name)]
}
- /** The API that all selects support */
+ /** The API that all selects support
+ * @group API
+ */
trait SelectApi extends RefTreeApi { this: Select =>
+ /** @inheritdoc */
val qualifier: Tree
+
+ /** @inheritdoc */
val name: Name
}
- /** Identifier <name> */
+ /** A reference to identifier `name`.
+ * @group Trees
+ * @template
+ */
type Ident >: Null <: RefTree with IdentApi
/** A tag that preserves the identity of the `Ident` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val IdentTag: ClassTag[Ident]
- /** The constructor/deconstructor for `Ident` instances. */
+ /** The constructor/deconstructor for `Ident` instances.
+ * @group Extractors
+ */
val Ident: IdentExtractor
/** An extractor class to create and pattern match with syntax `Ident(qual, name)`.
@@ -1406,32 +1915,42 @@ trait Trees { self: Universe =>
*
* Type checker converts idents that refer to enclosing fields or methods to selects.
* For example, name ==> this.name
+ * @group Extractors
*/
abstract class IdentExtractor {
def apply(name: Name): Ident
def unapply(ident: Ident): Option[Name]
}
- /** The API that all idents support */
+ /** The API that all idents support
+ * @group API
+ */
trait IdentApi extends RefTreeApi { this: Ident =>
+ /** @inheritdoc */
val name: Name
}
/** Marks underlying reference to id as boxed.
- * @pre id must refer to a captured variable
+ *
+ * <b>Precondition:<\b> id must refer to a captured variable
* A reference such marked will refer to the boxed entity, no dereferencing
* with `.elem` is done on it.
* This tree node can be emitted by macros such as reify that call referenceCapturedVariable.
* It is eliminated in LambdaLift, where the boxing conversion takes place.
+ * @group Trees
+ * @template
*/
type ReferenceToBoxed >: Null <: TermTree with ReferenceToBoxedApi
/** A tag that preserves the identity of the `ReferenceToBoxed` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val ReferenceToBoxedTag: ClassTag[ReferenceToBoxed]
- /** The constructor/deconstructor for `ReferenceToBoxed` instances. */
+ /** The constructor/deconstructor for `ReferenceToBoxed` instances.
+ * @group Extractors
+ */
val ReferenceToBoxed: ReferenceToBoxedExtractor
/** An extractor class to create and pattern match with syntax `ReferenceToBoxed(ident)`.
@@ -1452,40 +1971,54 @@ trait Trees { self: Universe =>
* Select(Ident(x), "elem")
*
* If `ReferenceToBoxed` were used instead of Ident, no transformation would be performed.
+ * @group Extractors
*/
abstract class ReferenceToBoxedExtractor {
def apply(ident: Ident): ReferenceToBoxed
def unapply(referenceToBoxed: ReferenceToBoxed): Option[Ident]
}
- /** The API that all references support */
+ /** The API that all references support
+ * @group API
+ */
trait ReferenceToBoxedApi extends TermTreeApi { this: ReferenceToBoxed =>
+ /** The underlying reference. */
val ident: Tree
}
- /** Literal */
+ /** Literal
+ * @group Trees
+ * @template
+ */
type Literal >: Null <: TermTree with LiteralApi
/** A tag that preserves the identity of the `Literal` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val LiteralTag: ClassTag[Literal]
- /** The constructor/deconstructor for `Literal` instances. */
+ /** The constructor/deconstructor for `Literal` instances.
+ * @group Extractors
+ */
val Literal: LiteralExtractor
/** An extractor class to create and pattern match with syntax `Literal(value)`.
* This AST node corresponds to the following Scala code:
*
* value
+ * @group Extractors
*/
abstract class LiteralExtractor {
def apply(value: Constant): Literal
def unapply(literal: Literal): Option[Constant]
}
- /** The API that all literals support */
+ /** The API that all literals support
+ * @group API
+ */
trait LiteralApi extends TermTreeApi { this: Literal =>
+ /** The compile-time constant underlying the literal. */
val value: Constant
}
@@ -1493,15 +2026,20 @@ trait Trees { self: Universe =>
* annotation ascriptions, annotations on definitions are stored in the Modifiers.
* Eliminated by typechecker (typedAnnotated), the annotations are then stored in
* an AnnotatedType.
+ * @group Trees
+ * @template
*/
type Annotated >: Null <: AnyRef with Tree with AnnotatedApi
/** A tag that preserves the identity of the `Annotated` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val AnnotatedTag: ClassTag[Annotated]
- /** The constructor/deconstructor for `Annotated` instances. */
+ /** The constructor/deconstructor for `Annotated` instances.
+ * @group Extractors
+ */
val Annotated: AnnotatedExtractor
/** An extractor class to create and pattern match with syntax `Annotated(annot, arg)`.
@@ -1509,54 +2047,76 @@ trait Trees { self: Universe =>
*
* arg @annot // for types
* arg: @annot // for exprs
+ * @group Extractors
*/
abstract class AnnotatedExtractor {
def apply(annot: Tree, arg: Tree): Annotated
def unapply(annotated: Annotated): Option[(Tree, Tree)]
}
- /** The API that all annotateds support */
+ /** The API that all annotateds support
+ * @group API
+ */
trait AnnotatedApi extends TreeApi { this: Annotated =>
+ /** The annotation. */
val annot: Tree
+
+ /** The annotee. */
val arg: Tree
}
- /** Singleton type, eliminated by RefCheck */
+ /** Singleton type, eliminated by RefCheck
+ * @group Trees
+ * @template
+ */
type SingletonTypeTree >: Null <: TypTree with SingletonTypeTreeApi
/** A tag that preserves the identity of the `SingletonTypeTree` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val SingletonTypeTreeTag: ClassTag[SingletonTypeTree]
- /** The constructor/deconstructor for `SingletonTypeTree` instances. */
+ /** The constructor/deconstructor for `SingletonTypeTree` instances.
+ * @group Extractors
+ */
val SingletonTypeTree: SingletonTypeTreeExtractor
/** An extractor class to create and pattern match with syntax `SingletonTypeTree(ref)`.
* This AST node corresponds to the following Scala code:
*
* ref.type
+ * @group Extractors
*/
abstract class SingletonTypeTreeExtractor {
def apply(ref: Tree): SingletonTypeTree
def unapply(singletonTypeTree: SingletonTypeTree): Option[Tree]
}
- /** The API that all singleton type trees support */
+ /** The API that all singleton type trees support
+ * @group API
+ */
trait SingletonTypeTreeApi extends TypTreeApi { this: SingletonTypeTree =>
+ /** The underlying reference. */
val ref: Tree
}
- /** Type selection <qualifier> # <name>, eliminated by RefCheck */
+ /** Type selection <qualifier> # <name>, eliminated by RefCheck
+ * @group Trees
+ * @template
+ */
// [Eugene++] don't see why we need it, when we have Select
type SelectFromTypeTree >: Null <: TypTree with RefTree with SelectFromTypeTreeApi
/** A tag that preserves the identity of the `SelectFromTypeTree` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val SelectFromTypeTreeTag: ClassTag[SelectFromTypeTree]
- /** The constructor/deconstructor for `SelectFromTypeTree` instances. */
+ /** The constructor/deconstructor for `SelectFromTypeTree` instances.
+ * @group Extractors
+ */
val SelectFromTypeTree: SelectFromTypeTreeExtractor
/** An extractor class to create and pattern match with syntax `SelectFromTypeTree(qualifier, name)`.
@@ -1565,151 +2125,219 @@ trait Trees { self: Universe =>
* qualifier # selector
*
* Note: a path-dependent type p.T is expressed as p.type # T
+ * @group Extractors
*/
abstract class SelectFromTypeTreeExtractor {
def apply(qualifier: Tree, name: TypeName): SelectFromTypeTree
def unapply(selectFromTypeTree: SelectFromTypeTree): Option[(Tree, TypeName)]
}
- /** The API that all selects from type trees support */
+ /** The API that all selects from type trees support
+ * @group API
+ */
trait SelectFromTypeTreeApi extends TypTreeApi with RefTreeApi { this: SelectFromTypeTree =>
+ /** @inheritdoc */
val qualifier: Tree
+
+ /** @inheritdoc */
val name: TypeName
}
- /** Intersection type <parent1> with ... with <parentN> { <decls> }, eliminated by RefCheck */
+ /** Intersection type <parent1> with ... with <parentN> { <decls> }, eliminated by RefCheck
+ * @group Trees
+ * @template
+ */
type CompoundTypeTree >: Null <: TypTree with CompoundTypeTreeApi
/** A tag that preserves the identity of the `CompoundTypeTree` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val CompoundTypeTreeTag: ClassTag[CompoundTypeTree]
- /** The constructor/deconstructor for `CompoundTypeTree` instances. */
+ /** The constructor/deconstructor for `CompoundTypeTree` instances.
+ * @group Extractors
+ */
val CompoundTypeTree: CompoundTypeTreeExtractor
/** An extractor class to create and pattern match with syntax `CompoundTypeTree(templ)`.
* This AST node corresponds to the following Scala code:
*
* parent1 with ... with parentN { refinement }
+ * @group Extractors
*/
abstract class CompoundTypeTreeExtractor {
def apply(templ: Template): CompoundTypeTree
def unapply(compoundTypeTree: CompoundTypeTree): Option[Template]
}
- /** The API that all compound type trees support */
+ /** The API that all compound type trees support
+ * @group API
+ */
trait CompoundTypeTreeApi extends TypTreeApi { this: CompoundTypeTree =>
+ /** The template of the compound type - represents the parents, the optional self-type and the optional definitions. */
val templ: Template
}
- /** Applied type <tpt> [ <args> ], eliminated by RefCheck */
+ /** Applied type <tpt> [ <args> ], eliminated by RefCheck
+ * @group Trees
+ * @template
+ */
type AppliedTypeTree >: Null <: TypTree with AppliedTypeTreeApi
/** A tag that preserves the identity of the `AppliedTypeTree` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val AppliedTypeTreeTag: ClassTag[AppliedTypeTree]
- /** The constructor/deconstructor for `AppliedTypeTree` instances. */
+ /** The constructor/deconstructor for `AppliedTypeTree` instances.
+ * @group Extractors
+ */
val AppliedTypeTree: AppliedTypeTreeExtractor
/** An extractor class to create and pattern match with syntax `AppliedTypeTree(tpt, args)`.
* This AST node corresponds to the following Scala code:
*
* tpt[args]
+ * @group Extractors
*/
abstract class AppliedTypeTreeExtractor {
def apply(tpt: Tree, args: List[Tree]): AppliedTypeTree
def unapply(appliedTypeTree: AppliedTypeTree): Option[(Tree, List[Tree])]
}
- /** The API that all applied type trees support */
+ /** The API that all applied type trees support
+ * @group API
+ */
trait AppliedTypeTreeApi extends TypTreeApi { this: AppliedTypeTree =>
+ /** The target of the application. */
val tpt: Tree
+
+ /** The arguments of the application. */
val args: List[Tree]
}
- /** Document me! */
+ /** Type bounds tree node
+ * @group Trees
+ * @template
+ */
type TypeBoundsTree >: Null <: TypTree with TypeBoundsTreeApi
/** A tag that preserves the identity of the `TypeBoundsTree` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val TypeBoundsTreeTag: ClassTag[TypeBoundsTree]
- /** The constructor/deconstructor for `TypeBoundsTree` instances. */
+ /** The constructor/deconstructor for `TypeBoundsTree` instances.
+ * @group Extractors
+ */
val TypeBoundsTree: TypeBoundsTreeExtractor
/** An extractor class to create and pattern match with syntax `TypeBoundsTree(lo, hi)`.
* This AST node corresponds to the following Scala code:
*
* >: lo <: hi
+ * @group Extractors
*/
abstract class TypeBoundsTreeExtractor {
def apply(lo: Tree, hi: Tree): TypeBoundsTree
def unapply(typeBoundsTree: TypeBoundsTree): Option[(Tree, Tree)]
}
- /** The API that all type bound trees support */
+ /** The API that all type bound trees support
+ * @group API
+ */
trait TypeBoundsTreeApi extends TypTreeApi { this: TypeBoundsTree =>
+ /** The lower bound.
+ * Is equal to `Ident(<scala.Nothing>)` if not specified explicitly.
+ */
val lo: Tree
+
+ /** The upper bound.
+ * Is equal to `Ident(<scala.Any>)` if not specified explicitly.
+ */
val hi: Tree
}
- /** Document me! */
+ /** Existential type tree node
+ * @group Trees
+ * @template
+ */
type ExistentialTypeTree >: Null <: TypTree with ExistentialTypeTreeApi
/** A tag that preserves the identity of the `ExistentialTypeTree` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val ExistentialTypeTreeTag: ClassTag[ExistentialTypeTree]
- /** The constructor/deconstructor for `ExistentialTypeTree` instances. */
+ /** The constructor/deconstructor for `ExistentialTypeTree` instances.
+ * @group Extractors
+ */
val ExistentialTypeTree: ExistentialTypeTreeExtractor
/** An extractor class to create and pattern match with syntax `ExistentialTypeTree(tpt, whereClauses)`.
* This AST node corresponds to the following Scala code:
*
* tpt forSome { whereClauses }
+ * @group Extractors
*/
abstract class ExistentialTypeTreeExtractor {
def apply(tpt: Tree, whereClauses: List[Tree]): ExistentialTypeTree
def unapply(existentialTypeTree: ExistentialTypeTree): Option[(Tree, List[Tree])]
}
- /** The API that all existential type trees support */
+ /** The API that all existential type trees support
+ * @group API
+ */
trait ExistentialTypeTreeApi extends TypTreeApi { this: ExistentialTypeTree =>
+ /** The underlying type of the existential type. */
val tpt: Tree
+
+ /** The clauses of the definition of the existential type. */
val whereClauses: List[Tree]
}
/** A synthetic tree holding an arbitrary type. Not to be confused with
- * with TypTree, the trait for trees that are only used for type trees.
- * TypeTree's are inserted in several places, but most notably in
- * `RefCheck`, where the arbitrary type trees are all replaced by
- * TypeTree's. */
+ * with TypTree, the trait for trees that are only used for type trees.
+ * TypeTree's are inserted in several places, but most notably in
+ * `RefCheck`, where the arbitrary type trees are all replaced by
+ * TypeTree's.
+ * @group Trees
+ * @template
+ */
type TypeTree >: Null <: TypTree with TypeTreeApi
/** A tag that preserves the identity of the `TypeTree` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val TypeTreeTag: ClassTag[TypeTree]
- /** The constructor/deconstructor for `TypeTree` instances. */
+ /** The constructor/deconstructor for `TypeTree` instances.
+ * @group Extractors
+ */
val TypeTree: TypeTreeExtractor
/** An extractor class to create and pattern match with syntax `TypeTree()`.
* This AST node does not have direct correspondence to Scala code,
* and is emitted by everywhere when we want to wrap a `Type` in a `Tree`.
+ * @group Extractors
*/
abstract class TypeTreeExtractor {
def apply(): TypeTree
def unapply(typeTree: TypeTree): Boolean
}
- /** The API that all type trees support */
+ /** The API that all type trees support
+ * @group API
+ */
trait TypeTreeApi extends TypTreeApi { this: TypeTree =>
+ /** The precursor of this tree.
+ * Is equal to `EmptyTree` if this type tree doesn't have precursors.
+ */
def original: Tree
}
@@ -1717,156 +2345,415 @@ trait Trees { self: Universe =>
* val _: _
* This is used as a placeholder in the `self` parameter Template if there is
* no definition of a self value of self type.
+ * @group Trees
*/
val emptyValDef: ValDef
// ---------------------- factories ----------------------------------------------
- /** @param sym the class symbol
- * @param impl the implementation template
+ /** A factory method for `ClassDef` nodes.
+ * @group Factories
*/
def ClassDef(sym: Symbol, impl: Template): ClassDef
- /**
- * @param sym the class symbol
- * @param impl the implementation template
+ /** A factory method for `ModuleDef` nodes.
+ * @group Factories
*/
def ModuleDef(sym: Symbol, impl: Template): ModuleDef
+ /** A factory method for `ValDef` nodes.
+ * @group Factories
+ */
def ValDef(sym: Symbol, rhs: Tree): ValDef
+ /** A factory method for `ValDef` nodes.
+ * @group Factories
+ */
def ValDef(sym: Symbol): ValDef
+ /** A factory method for `ValDef` nodes.
+ * @group Factories
+ */
def DefDef(sym: Symbol, mods: Modifiers, vparamss: List[List[ValDef]], rhs: Tree): DefDef
+ /** A factory method for `ValDef` nodes.
+ * @group Factories
+ */
def DefDef(sym: Symbol, vparamss: List[List[ValDef]], rhs: Tree): DefDef
+ /** A factory method for `ValDef` nodes.
+ * @group Factories
+ */
def DefDef(sym: Symbol, mods: Modifiers, rhs: Tree): DefDef
+ /** A factory method for `ValDef` nodes.
+ * @group Factories
+ */
def DefDef(sym: Symbol, rhs: Tree): DefDef
+ /** A factory method for `ValDef` nodes.
+ * @group Factories
+ */
def DefDef(sym: Symbol, rhs: List[List[Symbol]] => Tree): DefDef
- /** A TypeDef node which defines given `sym` with given tight hand side `rhs`. */
+ /** A factory method for `TypeDef` nodes.
+ * @group Factories
+ */
def TypeDef(sym: Symbol, rhs: Tree): TypeDef
- /** A TypeDef node which defines abstract type or type parameter for given `sym` */
+ /** A factory method for `TypeDef` nodes.
+ * @group Factories
+ */
def TypeDef(sym: Symbol): TypeDef
+ /** A factory method for `LabelDef` nodes.
+ * @group Factories
+ */
def LabelDef(sym: Symbol, params: List[Symbol], rhs: Tree): LabelDef
- /** Block factory that flattens directly nested blocks.
+ /** A factory method for `Block` nodes.
+ * Flattens directly nested blocks.
+ * @group Factories
*/
def Block(stats: Tree*): Block
- /** casedef shorthand */
+ /** A factory method for `CaseDef` nodes.
+ * @group Factories
+ */
def CaseDef(pat: Tree, body: Tree): CaseDef
+ /** A factory method for `Bind` nodes.
+ * @group Factories
+ */
def Bind(sym: Symbol, body: Tree): Bind
+ /** A factory method for `Try` nodes.
+ * @group Factories
+ */
def Try(body: Tree, cases: (Tree, Tree)*): Try
+ /** A factory method for `Throw` nodes.
+ * @group Factories
+ */
def Throw(tpe: Type, args: Tree*): Throw
/** Factory method for object creation `new tpt(args_1)...(args_n)`
* A `New(t, as)` is expanded to: `(new t).<init>(as)`
+ * @group Factories
*/
def New(tpt: Tree, argss: List[List[Tree]]): Tree
/** 0-1 argument list new, based on a type.
+ * @group Factories
*/
def New(tpe: Type, args: Tree*): Tree
+ /** 0-1 argument list new, based on a symbol.
+ * @group Factories
+ */
def New(sym: Symbol, args: Tree*): Tree
+ /** A factory method for `Apply` nodes.
+ * @group Factories
+ */
def Apply(sym: Symbol, args: Tree*): Tree
+ /** 0-1 argument list new, based on a type tree.
+ * @group Factories
+ */
def ApplyConstructor(tpt: Tree, args: List[Tree]): Tree
+ /** A factory method for `Super` nodes.
+ * @group Factories
+ */
def Super(sym: Symbol, mix: TypeName): Tree
+ /** A factory method for `This` nodes.
+ * @group Factories
+ */
def This(sym: Symbol): Tree
+ /** A factory method for `Select` nodes.
+ * The string `name` argument is assumed to represent a [[scala.reflect.api.Names#TermName `TermName`]].
+ * @group Factories
+ */
def Select(qualifier: Tree, name: String): Select
+ /** A factory method for `Select` nodes.
+ * @group Factories
+ */
def Select(qualifier: Tree, sym: Symbol): Select
+ /** A factory method for `Ident` nodes.
+ * @group Factories
+ */
def Ident(name: String): Ident
+ /** A factory method for `Ident` nodes.
+ * @group Factories
+ */
def Ident(sym: Symbol): Ident
+ /** A factory method for `TypeTree` nodes.
+ * @group Factories
+ */
def TypeTree(tp: Type): TypeTree
// ---------------------- copying ------------------------------------------------
- /** The standard (lazy) tree copier
+ /** The type of standard (lazy) tree copiers.
+ * @template
+ * @group Copying
*/
type TreeCopier <: TreeCopierOps
+
+ /** The standard (lazy) tree copier.
+ * @group Copying
+ */
val treeCopy: TreeCopier = newLazyTreeCopier
+ /** Creates a strict tree copier.
+ * @group Copying
+ */
def newStrictTreeCopier: TreeCopier
+
+ /** Creates a lazy tree copier.
+ * @group Copying
+ */
def newLazyTreeCopier: TreeCopier
- /** The API of a tree copier
- * tree copiers are made available by an implicit conversion in reflect.ops
+ /** The API of a tree copier.
+ * @group API
*/
abstract class TreeCopierOps {
+ /** Creates a `ClassDef` node from the given components, having a given `tree` as a prototype.
+ * Having a tree as a prototype means that the tree's attachments, type and symbol will be copied into the result.
+ */
def ClassDef(tree: Tree, mods: Modifiers, name: Name, tparams: List[TypeDef], impl: Template): ClassDef
+
+ /** Creates a `PackageDef` node from the given components, having a given `tree` as a prototype.
+ * Having a tree as a prototype means that the tree's attachments, type and symbol will be copied into the result.
+ */
def PackageDef(tree: Tree, pid: RefTree, stats: List[Tree]): PackageDef
+
+ /** Creates a `ModuleDef` node from the given components, having a given `tree` as a prototype.
+ * Having a tree as a prototype means that the tree's attachments, type and symbol will be copied into the result.
+ */
def ModuleDef(tree: Tree, mods: Modifiers, name: Name, impl: Template): ModuleDef
+
+ /** Creates a `ValDef` node from the given components, having a given `tree` as a prototype.
+ * Having a tree as a prototype means that the tree's attachments, type and symbol will be copied into the result.
+ */
def ValDef(tree: Tree, mods: Modifiers, name: Name, tpt: Tree, rhs: Tree): ValDef
+
+ /** Creates a `DefDef` node from the given components, having a given `tree` as a prototype.
+ * Having a tree as a prototype means that the tree's attachments, type and symbol will be copied into the result.
+ */
def DefDef(tree: Tree, mods: Modifiers, name: Name, tparams: List[TypeDef], vparamss: List[List[ValDef]], tpt: Tree, rhs: Tree): DefDef
+
+ /** Creates a `TypeDef` node from the given components, having a given `tree` as a prototype.
+ * Having a tree as a prototype means that the tree's attachments, type and symbol will be copied into the result.
+ */
def TypeDef(tree: Tree, mods: Modifiers, name: Name, tparams: List[TypeDef], rhs: Tree): TypeDef
+
+ /** Creates a `LabelDef` node from the given components, having a given `tree` as a prototype.
+ * Having a tree as a prototype means that the tree's attachments, type and symbol will be copied into the result.
+ */
def LabelDef(tree: Tree, name: Name, params: List[Ident], rhs: Tree): LabelDef
+
+ /** Creates a `Import` node from the given components, having a given `tree` as a prototype.
+ * Having a tree as a prototype means that the tree's attachments, type and symbol will be copied into the result.
+ */
def Import(tree: Tree, expr: Tree, selectors: List[ImportSelector]): Import
+
+ /** Creates a `Template` node from the given components, having a given `tree` as a prototype.
+ * Having a tree as a prototype means that the tree's attachments, type and symbol will be copied into the result.
+ */
def Template(tree: Tree, parents: List[Tree], self: ValDef, body: List[Tree]): Template
+
+ /** Creates a `Block` node from the given components, having a given `tree` as a prototype.
+ * Having a tree as a prototype means that the tree's attachments, type and symbol will be copied into the result.
+ */
def Block(tree: Tree, stats: List[Tree], expr: Tree): Block
+
+ /** Creates a `CaseDef` node from the given components, having a given `tree` as a prototype.
+ * Having a tree as a prototype means that the tree's attachments, type and symbol will be copied into the result.
+ */
def CaseDef(tree: Tree, pat: Tree, guard: Tree, body: Tree): CaseDef
+
+ /** Creates a `Alternative` node from the given components, having a given `tree` as a prototype.
+ * Having a tree as a prototype means that the tree's attachments, type and symbol will be copied into the result.
+ */
def Alternative(tree: Tree, trees: List[Tree]): Alternative
+
+ /** Creates a `Star` node from the given components, having a given `tree` as a prototype.
+ * Having a tree as a prototype means that the tree's attachments, type and symbol will be copied into the result.
+ */
def Star(tree: Tree, elem: Tree): Star
+
+ /** Creates a `Bind` node from the given components, having a given `tree` as a prototype.
+ * Having a tree as a prototype means that the tree's attachments, type and symbol will be copied into the result.
+ */
def Bind(tree: Tree, name: Name, body: Tree): Bind
+
+ /** Creates a `UnApply` node from the given components, having a given `tree` as a prototype.
+ * Having a tree as a prototype means that the tree's attachments, type and symbol will be copied into the result.
+ */
def UnApply(tree: Tree, fun: Tree, args: List[Tree]): UnApply
+
+ /** Creates a `Function` node from the given components, having a given `tree` as a prototype.
+ * Having a tree as a prototype means that the tree's attachments, type and symbol will be copied into the result.
+ */
def Function(tree: Tree, vparams: List[ValDef], body: Tree): Function
+
+ /** Creates a `Assign` node from the given components, having a given `tree` as a prototype.
+ * Having a tree as a prototype means that the tree's attachments, type and symbol will be copied into the result.
+ */
def Assign(tree: Tree, lhs: Tree, rhs: Tree): Assign
+
+ /** Creates a `AssignOrNamedArg` node from the given components, having a given `tree` as a prototype.
+ * Having a tree as a prototype means that the tree's attachments, type and symbol will be copied into the result.
+ */
def AssignOrNamedArg(tree: Tree, lhs: Tree, rhs: Tree): AssignOrNamedArg
+
+ /** Creates a `If` node from the given components, having a given `tree` as a prototype.
+ * Having a tree as a prototype means that the tree's attachments, type and symbol will be copied into the result.
+ */
def If(tree: Tree, cond: Tree, thenp: Tree, elsep: Tree): If
+
+ /** Creates a `Match` node from the given components, having a given `tree` as a prototype.
+ * Having a tree as a prototype means that the tree's attachments, type and symbol will be copied into the result.
+ */
def Match(tree: Tree, selector: Tree, cases: List[CaseDef]): Match
+
+ /** Creates a `Return` node from the given components, having a given `tree` as a prototype.
+ * Having a tree as a prototype means that the tree's attachments, type and symbol will be copied into the result.
+ */
def Return(tree: Tree, expr: Tree): Return
+
+ /** Creates a `Try` node from the given components, having a given `tree` as a prototype.
+ * Having a tree as a prototype means that the tree's attachments, type and symbol will be copied into the result.
+ */
def Try(tree: Tree, block: Tree, catches: List[CaseDef], finalizer: Tree): Try
+
+ /** Creates a `Throw` node from the given components, having a given `tree` as a prototype.
+ * Having a tree as a prototype means that the tree's attachments, type and symbol will be copied into the result.
+ */
def Throw(tree: Tree, expr: Tree): Throw
+
+ /** Creates a `New` node from the given components, having a given `tree` as a prototype.
+ * Having a tree as a prototype means that the tree's attachments, type and symbol will be copied into the result.
+ */
def New(tree: Tree, tpt: Tree): New
+
+ /** Creates a `Typed` node from the given components, having a given `tree` as a prototype.
+ * Having a tree as a prototype means that the tree's attachments, type and symbol will be copied into the result.
+ */
def Typed(tree: Tree, expr: Tree, tpt: Tree): Typed
+
+ /** Creates a `TypeApply` node from the given components, having a given `tree` as a prototype.
+ * Having a tree as a prototype means that the tree's attachments, type and symbol will be copied into the result.
+ */
def TypeApply(tree: Tree, fun: Tree, args: List[Tree]): TypeApply
+
+ /** Creates a `Apply` node from the given components, having a given `tree` as a prototype.
+ * Having a tree as a prototype means that the tree's attachments, type and symbol will be copied into the result.
+ */
def Apply(tree: Tree, fun: Tree, args: List[Tree]): Apply
+
+ /** Creates a `Super` node from the given components, having a given `tree` as a prototype.
+ * Having a tree as a prototype means that the tree's attachments, type and symbol will be copied into the result.
+ */
def Super(tree: Tree, qual: Tree, mix: TypeName): Super
+
+ /** Creates a `This` node from the given components, having a given `tree` as a prototype.
+ * Having a tree as a prototype means that the tree's attachments, type and symbol will be copied into the result.
+ */
def This(tree: Tree, qual: Name): This
+
+ /** Creates a `Select` node from the given components, having a given `tree` as a prototype.
+ * Having a tree as a prototype means that the tree's attachments, type and symbol will be copied into the result.
+ */
def Select(tree: Tree, qualifier: Tree, selector: Name): Select
+
+ /** Creates a `Ident` node from the given components, having a given `tree` as a prototype.
+ * Having a tree as a prototype means that the tree's attachments, type and symbol will be copied into the result.
+ */
def Ident(tree: Tree, name: Name): Ident
+
+ /** Creates a `ReferenceToBoxed` node from the given components, having a given `tree` as a prototype.
+ * Having a tree as a prototype means that the tree's attachments, type and symbol will be copied into the result.
+ */
def ReferenceToBoxed(tree: Tree, idt: Ident): ReferenceToBoxed
+
+ /** Creates a `Literal` node from the given components, having a given `tree` as a prototype.
+ * Having a tree as a prototype means that the tree's attachments, type and symbol will be copied into the result.
+ */
def Literal(tree: Tree, value: Constant): Literal
+
+ /** Creates a `TypeTree` node from the given components, having a given `tree` as a prototype.
+ * Having a tree as a prototype means that the tree's attachments, type and symbol will be copied into the result.
+ */
def TypeTree(tree: Tree): TypeTree
+
+ /** Creates a `Annotated` node from the given components, having a given `tree` as a prototype.
+ * Having a tree as a prototype means that the tree's attachments, type and symbol will be copied into the result.
+ */
def Annotated(tree: Tree, annot: Tree, arg: Tree): Annotated
+
+ /** Creates a `SingletonTypeTree` node from the given components, having a given `tree` as a prototype.
+ * Having a tree as a prototype means that the tree's attachments, type and symbol will be copied into the result.
+ */
def SingletonTypeTree(tree: Tree, ref: Tree): SingletonTypeTree
+
+ /** Creates a `SelectFromTypeTree` node from the given components, having a given `tree` as a prototype.
+ * Having a tree as a prototype means that the tree's attachments, type and symbol will be copied into the result.
+ */
def SelectFromTypeTree(tree: Tree, qualifier: Tree, selector: Name): SelectFromTypeTree
+
+ /** Creates a `CompoundTypeTree` node from the given components, having a given `tree` as a prototype.
+ * Having a tree as a prototype means that the tree's attachments, type and symbol will be copied into the result.
+ */
def CompoundTypeTree(tree: Tree, templ: Template): CompoundTypeTree
+
+ /** Creates a `AppliedTypeTree` node from the given components, having a given `tree` as a prototype.
+ * Having a tree as a prototype means that the tree's attachments, type and symbol will be copied into the result.
+ */
def AppliedTypeTree(tree: Tree, tpt: Tree, args: List[Tree]): AppliedTypeTree
+
+ /** Creates a `TypeBoundsTree` node from the given components, having a given `tree` as a prototype.
+ * Having a tree as a prototype means that the tree's attachments, type and symbol will be copied into the result.
+ */
def TypeBoundsTree(tree: Tree, lo: Tree, hi: Tree): TypeBoundsTree
+
+ /** Creates a `ExistentialTypeTree` node from the given components, having a given `tree` as a prototype.
+ * Having a tree as a prototype means that the tree's attachments, type and symbol will be copied into the result.
+ */
def ExistentialTypeTree(tree: Tree, tpt: Tree, whereClauses: List[Tree]): ExistentialTypeTree
}
// ---------------------- traversing and transforming ------------------------------
+ /** A class that implement a default tree traversal strategy: breadth-first component-wise.
+ * @group Traversal
+ */
class Traverser {
protected[scala] var currentOwner: Symbol = rootMirror.RootClass
+ /** Traverses a single tree. */
def traverse(tree: Tree): Unit = itraverse(this, tree)
+ /** Traverses a list of trees. */
def traverseTrees(trees: List[Tree]) {
trees foreach traverse
}
+
+ /** Traverses a list of lists of trees. */
def traverseTreess(treess: List[List[Tree]]) {
treess foreach traverseTrees
}
+
+ /** Traverses a list of trees with a given owner symbol. */
def traverseStats(stats: List[Tree], exprOwner: Symbol) {
stats foreach (stat =>
if (exprOwner != currentOwner) atOwner(exprOwner)(traverse(stat))
@@ -1874,6 +2761,7 @@ trait Trees { self: Universe =>
)
}
+ /** Performs a traversal with a given owner symbol. */
def atOwner(owner: Symbol)(traverse: => Unit) {
val prevOwner = currentOwner
currentOwner = owner
@@ -1886,49 +2774,81 @@ trait Trees { self: Universe =>
def apply[T <: Tree](tree: T): T = { traverse(tree); tree }
}
+ /** Delegates the traversal strategy to `scala.reflect.internal.Trees`,
+ * because pattern matching on abstract types we have here degrades performance.
+ * @group Traversal
+ */
protected def itraverse(traverser: Traverser, tree: Tree): Unit = throw new MatchError(tree)
+ /** Provides an extension hook for the traversal strategy.
+ * Future-proofs against new node types.
+ * @group Traversal
+ */
protected def xtraverse(traverser: Traverser, tree: Tree): Unit = throw new MatchError(tree)
+ /** A class that implement a default tree transformation strategy: breadth-first component-wise cloning.
+ * @group Traversal
+ */
abstract class Transformer {
+ /** The underlying tree copier. */
val treeCopy: TreeCopier = newLazyTreeCopier
+
+ /** The current owner symbol. */
protected[scala] var currentOwner: Symbol = rootMirror.RootClass
+
+ /** The enclosing method of the currently transformed tree. */
protected def currentMethod = {
def enclosingMethod(sym: Symbol): Symbol =
if (sym.isMethod || sym == NoSymbol) sym else enclosingMethod(sym.owner)
enclosingMethod(currentOwner)
}
+
+ /** The enclosing class of the currently transformed tree. */
protected def currentClass = {
def enclosingClass(sym: Symbol): Symbol =
if (sym.isClass || sym == NoSymbol) sym else enclosingClass(sym.owner)
enclosingClass(currentOwner)
}
+
// protected def currentPackage = currentOwner.enclosingTopLevelClass.owner
+
+ /** Transforms a single tree. */
def transform(tree: Tree): Tree = itransform(this, tree)
- def transformTrees(trees: List[Tree]): List[Tree] =
- trees mapConserve (transform(_))
+ /** Transforms a list of trees. */
+ def transformTrees(trees: List[Tree]): List[Tree] = trees mapConserve (transform(_))
+
+ /** Transforms a `Template`. */
def transformTemplate(tree: Template): Template =
transform(tree: Tree).asInstanceOf[Template]
+ /** Transforms a list of `TypeDef` trees. */
def transformTypeDefs(trees: List[TypeDef]): List[TypeDef] =
trees mapConserve (tree => transform(tree).asInstanceOf[TypeDef])
+ /** Transforms a `ValDef`. */
def transformValDef(tree: ValDef): ValDef =
if (tree.isEmpty) tree else transform(tree).asInstanceOf[ValDef]
+ /** Transforms a list of `ValDef` nodes. */
def transformValDefs(trees: List[ValDef]): List[ValDef] =
trees mapConserve (transformValDef(_))
+ /** Transforms a list of lists of `ValDef` nodes. */
def transformValDefss(treess: List[List[ValDef]]): List[List[ValDef]] =
treess mapConserve (transformValDefs(_))
+ /** Transforms a list of `CaseDef` nodes. */
def transformCaseDefs(trees: List[CaseDef]): List[CaseDef] =
trees mapConserve (tree => transform(tree).asInstanceOf[CaseDef])
+ /** Transforms a list of `Ident` nodes. */
def transformIdents(trees: List[Ident]): List[Ident] =
trees mapConserve (tree => transform(tree).asInstanceOf[Ident])
+ /** Traverses a list of trees with a given owner symbol. */
def transformStats(stats: List[Tree], exprOwner: Symbol): List[Tree] =
stats mapConserve (stat =>
if (exprOwner != currentOwner && stat.isTerm) atOwner(exprOwner)(transform(stat))
else transform(stat)) filter (EmptyTree != _)
+ /** Transforms `Modifiers`. */
def transformModifiers(mods: Modifiers): Modifiers =
mods.mapAnnotations(transformTrees)
+ /** Transforms a tree with a given owner symbol. */
def atOwner[A](owner: Symbol)(trans: => A): A = {
val prevOwner = currentOwner
currentOwner = owner
@@ -1938,39 +2858,83 @@ trait Trees { self: Universe =>
}
}
+ /** Delegates the transformation strategy to `scala.reflect.internal.Trees`,
+ * because pattern matching on abstract types we have here degrades performance.
+ * @group Traversal
+ */
protected def itransform(transformer: Transformer, tree: Tree): Tree = throw new MatchError(tree)
+ /** Provides an extension hook for the transformation strategy.
+ * Future-proofs against new node types.
+ * @group Traversal
+ */
protected def xtransform(transformer: Transformer, tree: Tree): Tree = throw new MatchError(tree)
-
- /** ... */
+ /** The type of tree modifiers.
+ * @group Traversal
+ */
type Modifiers >: Null <: AnyRef with ModifiersApi
/** A tag that preserves the identity of the `Modifiers` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Traversal
*/
implicit val ModifiersTag: ClassTag[Modifiers]
- /** ... */
+ /** The API that all Modifiers support
+ * @group API
+ */
abstract class ModifiersApi {
- def flags: FlagSet // default: NoFlags
+ /** The underlying flags of the enclosing definition.
+ * Is equal to `NoFlags` if none are specified explicitly.
+ */
+ def flags: FlagSet
+
def hasFlag(flag: FlagSet): Boolean
- def privateWithin: Name // default: EmptyTypeName
- def annotations: List[Tree] // default: List()
+
+ /** The visibility scope of the enclosing definition.
+ * Is equal to `tpnme.EMPTY` if none is specified explicitly.
+ */
+ def privateWithin: Name
+
+ /** The annotations of the enclosing definition.
+ * Empty list if none are specified explicitly.
+ */
+ def annotations: List[Tree]
+
+ /** Creates a new instance of `Modifiers` with
+ * the annotations transformed according to the given function.
+ */
def mapAnnotations(f: List[Tree] => List[Tree]): Modifiers =
Modifiers(flags, privateWithin, f(annotations))
}
+ /** The constructor/deconstructor for `Modifiers` instances.
+ * @group Traversal
+ */
val Modifiers: ModifiersCreator
+ /** An extractor class to create and pattern match with syntax `Modifiers(flags, privateWithin, annotations)`.
+ * Modifiers encapsulate flags, visibility annotations and Scala annotations for member definitions.
+ * @group Traversal
+ */
abstract class ModifiersCreator {
def apply(): Modifiers = Modifiers(NoFlags, tpnme.EMPTY, List())
def apply(flags: FlagSet, privateWithin: Name, annotations: List[Tree]): Modifiers
}
+ /** The factory for `Modifiers` instances.
+ * @group Traversal
+ */
def Modifiers(flags: FlagSet, privateWithin: Name): Modifiers = Modifiers(flags, privateWithin, List())
+
+ /** The factory for `Modifiers` instances.
+ * @group Traversal
+ */
def Modifiers(flags: FlagSet): Modifiers = Modifiers(flags, tpnme.EMPTY)
- /** ... */
+ /** An empty `Modifiers` object: no flags, empty visibility annotation and no Scala annotations.
+ * @group Traversal
+ */
lazy val NoMods = Modifiers()
}
diff --git a/src/reflect/scala/reflect/api/TypeCreator.scala b/src/reflect/scala/reflect/api/TypeCreator.scala
index 2b3ef4320b..9c386f2939 100644
--- a/src/reflect/scala/reflect/api/TypeCreator.scala
+++ b/src/reflect/scala/reflect/api/TypeCreator.scala
@@ -3,23 +3,7 @@ package api
/** A mirror-aware factory for types.
*
- * In the reflection API, artifacts are specific to universes and
- * symbolic references used in artifacts (e.g. `scala.Int`) are resolved by mirrors.
- *
- * Therefore to build a type one needs to know a universe that the type is going to be bound to
- * and a mirror that is going to resolve symbolic references (e.g. to determine that `scala.Int`
- * points to a core class `Int` from scala-library.jar).
- *
- * `TypeCreator` implements this notion by providing a standalone type factory.
- *
- * This is immediately useful for type tags. When the compiler creates a type tag,
- * the end result needs to make sense in any mirror. That's because the compiler knows
- * the universe it's creating a type tag for (since `TypeTag` is path-dependent on a universe),
- * but it cannot know in advance the mirror to instantiate the result in (e.g. on JVM
- * it doesn't know what classloader use to resolve symbolic names in the type tag).
- *
- * Due to a typechecker restriction (no eta-expansion for dependent method types),
- * `TypeCreator` can't have a functional type, so it's implemented as class with an apply method.
+ * This class is used internally by Scala Reflection, and is not recommended for use in client code.
*/
abstract class TypeCreator {
def apply[U <: Universe with Singleton](m: scala.reflect.api.Mirror[U]): U # Type
diff --git a/src/reflect/scala/reflect/api/TypeTags.scala b/src/reflect/scala/reflect/api/TypeTags.scala
index fc3f067a96..812d5199fc 100644
--- a/src/reflect/scala/reflect/api/TypeTags.scala
+++ b/src/reflect/scala/reflect/api/TypeTags.scala
@@ -18,143 +18,168 @@ import scala.language.implicitConversions
* Backwards compat item1: [Eugene++] it might be useful, though, to guard against abstractness of the incoming type.
*/
/**
- * A type tag encapsulates a representation of type T.
- *
- * Type tags replace the pre-2.10 concept of a [[scala.reflect.Manifest]] and are integrated with reflection.
- *
- * === Overview and examples ===
- *
- * Type tags are organized in a hierarchy of three classes:
- * [[scala.reflect.ClassTag]], [[scala.reflect.api.Universe#TypeTag]] and [[scala.reflect.api.Universe#WeakTypeTag]].
- *
- * @see [[scala.reflect.ClassTag]], [[scala.reflect.api.Universe#TypeTag]], [[scala.reflect.api.Universe#WeakTypeTag]]
- *
- * Examples:
- * {{{
- * scala> class Person
- * scala> class Container[T]
- * scala> import scala.reflect.ClassTag
- * scala> import scala.reflect.runtime.universe.TypeTag
- * scala> import scala.reflect.runtime.universe.WeakTypeTag
- * scala> def firstTypeArg( tag: WeakTypeTag[_] ) = (tag.tpe match {case TypeRef(_,_,typeArgs) => typeArgs})(0)
- * }}}
- * TypeTag contains concrete type arguments:
- * {{{
- * scala> firstTypeArg( implicitly[TypeTag[Container[Person]]] )
- * res0: reflect.runtime.universe.Type = Person
- * }}}
- * TypeTag guarantees concrete type arguments (fails for references to unbound type arguments):
- * {{{
- * scala> def foo1[T] = implicitly[TypeTag[Container[T]]]
- * <console>:11: error: No TypeTag available for Container[T]
- * def foo1[T] = implicitly[TypeTag[Container[T]]]
- * }}}
- * WeakTypeTag allows references to unbound type arguments:
- * {{{
- * scala> def foo2[T] = firstTypeArg( implicitly[WeakTypeTag[Container[T]]] )
- * foo2: [T]=> reflect.runtime.universe.Type
- * scala> foo2[Person]
- * res1: reflect.runtime.universe.Type = T
- * }}}
- * TypeTag allows unbound type arguments for which type tags are available:
- * {{{
- * scala> def foo3[T:TypeTag] = firstTypeArg( implicitly[TypeTag[Container[T]]] )
- * foo3: [T](implicit evidence$1: reflect.runtime.universe.TypeTag[T])reflect.runtime.universe.Type
- * scala> foo3[Person]
- * res1: reflect.runtime.universe.Type = Person
- * }}}
- * WeakTypeTag contains concrete type arguments if available via existing tags:
- * {{{
- * scala> def foo4[T:WeakTypeTag] = firstTypeArg( implicitly[WeakTypeTag[Container[T]]] )
- * foo4: [T](implicit evidence$1: reflect.runtime.universe.WeakTypeTag[T])reflect.runtime.universe.Type
- * scala> foo4[Person]
- * res1: reflect.runtime.universe.Type = Person
- * }}}
- *
- *
- * [[scala.reflect.api.Universe#TypeTag]] and [[scala.reflect.api.Universe#WeakTypeTag]] are path dependent on their universe.
- *
- * The default universe is [[scala.reflect.runtime.universe]]
- *
- * Type tags can be migrated to another universe given the corresponding mirror using
- *
- * {{{
- * tag.in( other_mirror )
- * }}}
- *
- * See [[scala.reflect.api.TypeTags#WeakTypeTag.in]]
- *
- * === WeakTypeTag vs TypeTag ===
- *
- * Be careful with WeakTypeTag, because it will reify types even if these types are abstract.
- * This makes it easy to forget to tag one of the methods in the call chain and discover it much later in the runtime
- * by getting cryptic errors far away from their source. For example, consider the following snippet:
+ * A `TypeTag[T]` encapsulates the runtime type representation of some type `T`.
+ * Like [[scala.reflect.Manifest]], the prime use case of `TypeTag`s is to give access
+ * to erased types. However, `TypeTag`s should be considered to be a richer
+ * replacement of the pre-2.10 notion of a [[scala.reflect.Manifest Manifest]], that
+ * are, in addition, fully integrated with Scala reflection.
+ *
+ * There exist three different types of `TypeTags`:
+ *
+ * <ul>
+ * <li>[[scala.reflect.api.TypeTags#TypeTag]]. <br/>A full type descriptor of a Scala type.
+ * For example, a `TypeTag[List[String]]` contains all type information,
+ * in this case, of type `scala.List[String]`.</li>
+ *
+ * <li>[[scala.reflect.ClassTag]]. <br/>A partial type descriptor of a Scala type. For
+ * example, a `ClassTag[List[String]]` contains only the erased class
+ * type information, in this case, of type `scala.collection.immutable.List`.
+ * `ClassTag`s provide access only to the runtime class of a type.
+ * Analogous to [[scala.reflect.ClassManifest]]</li>
+ *
+ * <li>[[scala.reflect.api.TypeTags#WeakTypeTag]]. <br/>A type descriptor for abstract
+ * types (see description below).</li>
+ * </ul>
+ *
+ * Like [[scala.reflect.Manifest Manifest]]s, `TypeTag`s are always generated by the
+ * compiler, and can be obtained in three ways:
+ *
+ * === #1 Via the methods [[scala.reflect.api.TypeTags#typeTag typeTag]],
+ * [[scala.reflect#classTag classTag]], or [[scala.reflect.api.TypeTags#weakTypeTag weakTypeTag]] ===
+ *
+ * For example:
+ * {{{
+ * import scala.reflect.runtime.universe._
+ * val tt = typeTag[Int]
+ *
+ * import scala.reflect._
+ * val ct = classTag[String]
+ * }}}
+ *
+ * Each of these methods constructs a `TypeTag[T]` or `ClassTag[T]` for the given
+ * type argument `T`.
+ *
+ * === #2 Using an implicit parameter of type `TypeTag[T]`, `ClassTag[T]`, or `WeakTypeTag[T]
+ *
+ * For example:
+ * {{{
+ * import scala.reflect.runtime.universe._
+ *
+ * def paramInfo[T](x: T)(implicit tag: TypeTag[T]): Unit = {
+ * val targs = tag.tpe match { case TypeRef(_, _, args) => args }
+ * println(s"type of $x has type arguments $targs")
+ * }
+ *
+ * scala> paramInfo(42)
+ * type of 42 has type arguments List()
+ *
+ * scala> paramInfo(List(1, 2))
+ * type of List(1, 2) has type arguments List(Int)
+ * }}}
+ *
+ * === #3 Context bound of a type parameter ===
+ *
+ * ...on methods or classes. The above example can be implemented as follows:
*
* {{{
- * def bind[T: WeakTypeTag](name: String, value: T): IR.Result = bind((name, value))
- * def bind(p: NamedParam): IR.Result = bind(p.name, p.tpe, p.value)
- * object NamedParam {
- * implicit def namedValue[T: WeakTypeTag](name: String, x: T): NamedParam = apply(name, x)
- * def apply[T: WeakTypeTag](name: String, x: T): NamedParam = new Typed[T](name, x)
+ * import scala.reflect.runtime.universe._
+ *
+ * def paramInfo[T: TypeTag](x: T): Unit = {
+ * val targs = typeOf[T] match { case TypeRef(_, _, args) => args }
+ * println(s"type of $x has type arguments $targs")
* }
+ *
+ * scala> paramInfo(42)
+ * type of 42 has type arguments List()
+ *
+ * scala> paramInfo(List(1, 2))
+ * type of List(1, 2) has type arguments List(Int)
* }}}
+ *
+ * === `WeakTypeTag`s ===
*
- * This fragment of the Scala REPL implementation defines a `bind` function that carries a named value along with its type
- * into the heart of the REPL. Using a [[scala.reflect.api.Universe#WeakTypeTag]] here is reasonable, because it is desirable
- * to work with all types, even if they are type parameters or abstract type members.
+ *`WeakTypeTag[T]` generalizes `TypeTag[T]`. Unlike a regular `TypeTag`, components of
+ * its type representation can be references to type parameters or abstract types.
+ * However, `WeakTypeTag[T]` tries to be as concrete as possible, i.e. if type tags
+ * are available for the referenced type arguments or abstract types, they are used to
+ * embed the concrete types into the `WeakTypeTag[T]`.
*
- * However if any of the three `WeakTypeTag` context bounds is omitted, the resulting code will be incorrect,
- * because the missing `WeakTypeTag` will be transparently generated by the compiler, carrying meaningless information.
- * Most likely, this problem will manifest itself elsewhere, making debugging complicated.
- * If `WeakTypeTag` context bounds were replaced with `TypeTag`, then such errors would be reported statically.
- * But in that case we wouldn't be able to use `bind` in arbitrary contexts.
+ * Continuing the example above:
+ * {{{
+ * def weakParamInfo[T](x: T)(implicit tag: WeakTypeTag[T]): Unit = {
+ * val targs = tag.tpe match { case TypeRef(_, _, args) => args }
+ * println(s"type of $x has type arguments $targs")
+ * }
+ *
+ * scala> def foo[T] = weakParamInfo(List[T]())
+ * foo: [T]=> Unit
*
- * === Backward compatibility with Manifests ===
+ * scala> foo[Int]
+ * type of List() has type arguments List(T)
+ * }}}
*
- * Type tags correspond loosely to manifests.
+ * === TypeTags and Manifests ===
*
- * More precisely:
- * The previous notion of a [[scala.reflect.ClassManifest]] corresponds to a scala.reflect.ClassTag,
- * The previous notion of a [[scala.reflect.Manifest]] corresponds to scala.reflect.runtime.universe.TypeTag,
+ * `TypeTag`s correspond loosely to the pre-2.10 notion of
+ * [[scala.reflect.Manifest]]s. While [[scala.reflect.ClassTag]] corresponds to
+ * [[scala.reflect.ClassManifest]] and [[scala.reflect.api.TypeTags#TypeTag]] mostly
+ * corresponds to [[scala.reflect.Manifest]], other pre-2.10 `Manifest` types do not
+ * have a direct correspondence with a 2.10 "`Tag`" type.
*
- * In Scala 2.10, manifests are deprecated, so it's advisable to migrate them to tags,
- * because manifests will probably be removed in the next major release.
+ * <ul>
+ * <li>'''[[scala.reflect.OptManifest]] is not supported.''' <br/>This is because `Tag`s
+ * can reify arbitrary types, so they are always available.<li>
*
- * In most cases it will be enough to replace ClassManifest with ClassTag and Manifest with TypeTag.
- * There are however a few caveats:
+ * <li>'''There is no equivalent for [[scala.reflect.AnyValManifest]].''' <br/>Instead, one
+ * can compare their `Tag` with one of the base `Tag`s (defined in the corresponding
+ * companion objects) in order to find out whether or not it represents a primitive
+ * value class. Additionally, it's possible to simply use
+ * `<tag>.tpe.typeSymbol.isPrimitiveValueClass`.</li>
*
- * 1) The notion of OptManifest is no longer supported. Tags can reify arbitrary types, so they are always available.
+ * <li>'''There are no replacement for factory methods defined in the `Manifest`
+ * companion objects'''. <br/>Instead, one could generate corresponding types using the
+ * reflection APIs provided by Java (for classes) and Scala (for types).</li>
*
- * 2) There's no equivalent for AnyValManifest. Consider comparing your tag with one of the base tags
- * (defined in the corresponding companion objects) to find out whether it represents a primitive value class.
- * You can also use `<tag>.tpe.typeSymbol.isPrimitiveValueClass` for that purpose (requires scala-reflect.jar).
+ * <li>'''Certain manifest operations(i.e., <:<, >:> and typeArguments) are not
+ * supported.''' <br/>Instead, one culd use the reflection APIs provided by Java (for
+ * classes) and Scala (for types).</li>
+ *</ul>
*
- * 3) There's no replacement for factory methods defined in `ClassManifest` and `Manifest` companion objects.
- * Consider assembling corresponding types using the reflection APIs provided by Java (for classes) and Scala (for types).
+ * In Scala 2.10, [[scala.reflect.ClassManifest]]s are deprecated, and it is planned
+ * to deprecate [[scala.reflect.Manifest]] in favor of `TypeTag`s and `ClassTag`s in
+ * an upcoming point release. Thus, it is advisable to migrate any `Manifest`-based
+ * APIs to use `Tag`s.
*
- * 4) Certain manifest functions (such as `<:<`, `>:>` and `typeArguments`) weren't included in the tag API.
- * Consider using the reflection APIs provided by Java (for classes) and Scala (for types) instead.
+ * For more information about `TypeTag`s, see the
+ * [[http://docs.scala-lang.org/overviews/reflection/typetags-manifests.html Reflection Guide: TypeTags]]
+ *
+ * @see [[scala.reflect.ClassTag]], [[scala.reflect.api.TypeTags#TypeTag]], [[scala.reflect.api.TypeTags#WeakTypeTag]]
+ * @group TypeTags Type Tags
*/
trait TypeTags { self: Universe =>
import definitions._
/**
- * If an implicit value of type WeakTypeTag[T] is required, the compiler will create one.
- * A reflective representation of T can be accessed via the tpe field.
- * Components of T can be references to type parameters or abstract types. WeakTypeTag makes an effort to
- * be as concrete as possible, i.e. if type tags are available for the referenced type arguments or abstract types,
- * they are used to embed the concrete types into the WeakTypeTag. Otherwise the WeakTypeTag will contain a reference
- * to an abstract type. This behavior can be useful, when one expects T to be possibly partially abstract, but
- * requires special care to handle this case. If however T is expected to be fully known, use
- * [[scala.reflect.api.Universe#TypeTag]] instead, which statically guarantees this property.
+ * If an implicit value of type `WeakTypeTag[T]` is required, the compiler will create one,
+ * and the reflective representation of `T` can be accessed via the `tpe` field.
+ * Components of `T` can be references to type parameters or abstract types. Note that `WeakTypeTag`
+ * makes an effort to be as concrete as possible, i.e. if `TypeTag`s are available for the referenced type arguments
+ * or abstract types, they are used to embed the concrete types into the WeakTypeTag. Otherwise the WeakTypeTag will
+ * contain a reference to an abstract type. This behavior can be useful, when one expects `T` to be perhaps be partially
+ * abstract, but requires special care to handle this case. However, if `T` is expected to be fully known, use
+ * [[scala.reflect.api.TypeTags#TypeTag]] instead, which statically guarantees this property.
+ *
+ * For more information about `TypeTag`s, see the
+ * [[http://docs.scala-lang.org/overviews/reflection/typetags-manifests.html Reflection Guide: TypeTags]]
*
* @see [[scala.reflect.api.TypeTags]]
+ * @group TypeTags
*/
@annotation.implicitNotFound(msg = "No WeakTypeTag available for ${T}")
trait WeakTypeTag[T] extends Equals with Serializable {
/**
- * Underlying mirror of this type tag.
+ * The underlying `Mirror` of this type tag.
*/
val mirror: Mirror
@@ -171,15 +196,22 @@ trait TypeTags { self: Universe =>
*/
def tpe: Type
- // case class accessories
+ // TODO how do I doc this?
override def canEqual(x: Any) = x.isInstanceOf[WeakTypeTag[_]]
+
+ // TODO how do I doc this?
override def equals(x: Any) = x.isInstanceOf[WeakTypeTag[_]] && this.mirror == x.asInstanceOf[WeakTypeTag[_]].mirror && this.tpe == x.asInstanceOf[WeakTypeTag[_]].tpe
+
+ // TODO how do I doc this?
override def hashCode = mirror.hashCode * 31 + tpe.hashCode
+
+ // TODO how do I doc this?
override def toString = "WeakTypeTag[" + tpe + "]"
}
/**
* Type tags corresponding to primitive types and constructor/extractor for WeakTypeTags.
+ * @group TypeTags
*/
object WeakTypeTag {
val Byte : WeakTypeTag[scala.Byte] = TypeTag.Byte
@@ -222,6 +254,7 @@ trait TypeTags { self: Universe =>
def unapply[T](ttag: WeakTypeTag[T]): Option[Type] = Some(ttag.tpe)
}
+ /* @group TypeTags */
private class WeakTypeTagImpl[T](val mirror: Mirror, val tpec: TypeCreator) extends WeakTypeTag[T] {
lazy val tpe: Type = tpec(mirror)
def in[U <: Universe with Singleton](otherMirror: scala.reflect.api.Mirror[U]): U # WeakTypeTag[T] = {
@@ -232,11 +265,12 @@ trait TypeTags { self: Universe =>
}
/**
- * A `TypeTag` is a [[scala.reflect.api.Universe#WeakTypeTag]] with the additional
+ * A `TypeTag` is a [[scala.reflect.api.TypeTags#WeakTypeTag]] with the additional
* static guarantee that all type references are concrete, i.e. it does <b>not</b> contain any references to
* unresolved type parameters or abstract types.
*
* @see [[scala.reflect.api.TypeTags]]
+ * @group TypeTags
*/
@annotation.implicitNotFound(msg = "No TypeTag available for ${T}")
trait TypeTag[T] extends WeakTypeTag[T] with Equals with Serializable {
@@ -245,13 +279,23 @@ trait TypeTags { self: Universe =>
*/
override def in[U <: Universe with Singleton](otherMirror: scala.reflect.api.Mirror[U]): U # TypeTag[T]
- // case class accessories
+ /** TODO how do I doc this? */
override def canEqual(x: Any) = x.isInstanceOf[TypeTag[_]]
+
+ /** TODO how do I doc this? */
override def equals(x: Any) = x.isInstanceOf[TypeTag[_]] && this.mirror == x.asInstanceOf[TypeTag[_]].mirror && this.tpe == x.asInstanceOf[TypeTag[_]].tpe
+
+ /** TODO how do I doc this? */
override def hashCode = mirror.hashCode * 31 + tpe.hashCode
+
+ /** TODO how do I doc this? */
override def toString = "TypeTag[" + tpe + "]"
}
+ /**
+ * Type tags corresponding to primitive types and constructor/extractor for WeakTypeTags.
+ * @group TypeTags
+ */
object TypeTag {
val Byte: TypeTag[scala.Byte] = new PredefTypeTag[scala.Byte] (ByteTpe, _.TypeTag.Byte)
val Short: TypeTag[scala.Short] = new PredefTypeTag[scala.Short] (ShortTpe, _.TypeTag.Short)
@@ -292,6 +336,7 @@ trait TypeTags { self: Universe =>
def unapply[T](ttag: TypeTag[T]): Option[Type] = Some(ttag.tpe)
}
+ /* @group TypeTags */
private class TypeTagImpl[T](mirror: Mirror, tpec: TypeCreator) extends WeakTypeTagImpl[T](mirror, tpec) with TypeTag[T] {
override def in[U <: Universe with Singleton](otherMirror: scala.reflect.api.Mirror[U]): U # TypeTag[T] = {
val otherMirror1 = otherMirror.asInstanceOf[scala.reflect.api.Mirror[otherMirror.universe.type]]
@@ -300,12 +345,14 @@ trait TypeTags { self: Universe =>
private def writeReplace(): AnyRef = new SerializedTypeTag(tpec, concrete = true)
}
+ /* @group TypeTags */
private class PredefTypeCreator[T](copyIn: Universe => Universe#TypeTag[T]) extends TypeCreator {
def apply[U <: Universe with Singleton](m: scala.reflect.api.Mirror[U]): U # Type = {
copyIn(m.universe).asInstanceOf[U # TypeTag[T]].tpe
}
}
+ /* @group TypeTags */
private class PredefTypeTag[T](_tpe: Type, copyIn: Universe => Universe#TypeTag[T]) extends TypeTagImpl[T](rootMirror, new PredefTypeCreator(copyIn)) {
override lazy val tpe: Type = _tpe
private def writeReplace(): AnyRef = new SerializedTypeTag(tpec, concrete = true)
@@ -313,22 +360,26 @@ trait TypeTags { self: Universe =>
/**
* Shortcut for `implicitly[WeakTypeTag[T]]`
+ * @group TypeTags
*/
def weakTypeTag[T](implicit attag: WeakTypeTag[T]) = attag
/**
* Shortcut for `implicitly[TypeTag[T]]`
+ * @group TypeTags
*/
def typeTag[T](implicit ttag: TypeTag[T]) = ttag
// big thanks to Viktor Klang for this brilliant idea!
/**
* Shortcut for `implicitly[WeakTypeTag[T]].tpe`
+ * @group TypeTags
*/
def weakTypeOf[T](implicit attag: WeakTypeTag[T]): Type = attag.tpe
/**
* Shortcut for `implicitly[TypeTag[T]].tpe`
+ * @group TypeTags
*/
def typeOf[T](implicit ttag: TypeTag[T]): Type = ttag.tpe
}
diff --git a/src/reflect/scala/reflect/api/Types.scala b/src/reflect/scala/reflect/api/Types.scala
index af70c9e761..2267f21609 100644
--- a/src/reflect/scala/reflect/api/Types.scala
+++ b/src/reflect/scala/reflect/api/Types.scala
@@ -1,37 +1,102 @@
package scala.reflect
package api
-/**
- * Defines the type hierachy for types.
+/** A trait that defines types and operations on them.
*
- * Note: Because of implementation details, some type factories have return type `Type`
- * instead of a more precise type.
+ * Type instances represent information about the type of a corresponding symbol. This includes its members
+ * (methods, fields, type parameters, nested classes, traits, etc) either declared directly or inherited, its base types,
+ * its erasure and so on. Types also provide operation to test for type conformance or euqivalence or for widening.
*
- * @see [[scala.reflect]] for a description on how the class hierarchy is encoded here.
+ * === Instantiating types ===
+ *
+ * There are three ways to instantiate types. The simplest one involves the [[scala.reflect.api.TypeTags#typeOf]] method,
+ * which takes a type argument and produces a `Type` instance that represents that argument. For example, `typeOf[List[Int]]`
+ * produces a [[scala.reflect.api.Types#TypeRef]], which corresponds to a type `List` applied to a type argument `Int`.
+ * Method `typeOf` does not work for types with type parameters, such as `typeOf[List[A]]` where `A` is a type variable.
+ * In this case, use [[scala.reflect.api.TypeTags#weakTypeOf]] instead. Refer to [[scala.reflect.api.TypeTags the type tags page]] to find out
+ * more about this distinction.
+ *
+ * `typeOf` requires spelling out a type explicitly, but there's also a way to capture types implicitly with the [[scala.reflect.api.TypeTags#TypeTag]]
+ * context bound. See [[scala.reflect.api.TypeTags the type tags page]] for details.
+ *
+ * Finally, types can be instantiated manually using factory methods such as `typeRef` or `polyType`.
+ * This is necessary only in cases when `typeOf` or `typeTag` cannot be applied because the type cannot be spelt out
+ * in a Scala snippet, usually when writing macros. Manual construction requires deep knowledge of Scala compiler internals
+ * and should be avoided if possible.
+ *
+ * === Using types ===
+ *
+ * Common operations on types are querying them for inner declarations or type conformance tests.
+ *
+ * Every type has `members` and `declarations` methods (along with their singular counterparts `member` and `declaration`),
+ * which provide the list of definitions associated with that type. For example, to look up the `map` method of `List`, one can
+ * write `typeOf[List[_]].member("map": TermName)`, getting a `MethodSymbol`
+ *
+ * Types expose `<:<` and `weak_<:<` methods to test for subtype relationships. The latter is an extension of the former - it also works
+ * with numeric types (for example, `Int <:< Long` is false, but `Int weak_<:< Long` is true). Unlike the subtype tests implemented by
+ * type tags, tests provided by `Type`s are aware of all the intricacies of the Scala type system and work correctly even for involved types.
+ *
+ * The vanilla `==` method should not be used to compare types for equality. Instead, one should always use the `=:=` method.
+ * Operator `=:=` knows about type aliases, e.g., `typeOf[scala.List[_]] =:= typeOf[scala.collection.immutable.List[_]]`.
+ *
+ * === Exploring types ===
+ *
+ * {{{
+ * scala> import scala.reflect.runtime.universe._
+ * import scala.reflect.runtime.universe._
+ *
+ * scala> typeOf[List[_]].members.sorted take 5 foreach println
+ * constructor List
+ * method companion
+ * method ::
+ * method :::
+ * method reverse_:::
+ *
+ * scala> def test[T: TypeTag](x: T) = s"I've been called for an x typed as \${typeOf[T]}"
+ * test: [T](x: T)(implicit evidence\$1: reflect.runtime.universe.TypeTag[T])String
+ *
+ * scala> test(2)
+ * res0 @ 3fc80fae: String = I've been called for an x typed as Int
+ *
+ * scala> test(List(2, "x"))
+ * res1 @ 10139edf: String = I've been called for an x typed as List[Any]
+ * }}}
+ *
+ * @groupname TypeCreators Types - Creation
+ * @groupname TypeOps Types - Operations
+ *
+ * @contentDiagram hideNodes "*Api"
*/
trait Types { self: Universe =>
/** The type of Scala types, and also Scala type signatures.
* (No difference is internally made between the two).
+ * @template
+ * @group Types
*/
type Type >: Null <: TypeApi
/** A tag that preserves the identity of the `Type` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val TypeTagg: ClassTag[Type]
/** This constant is used as a special value that indicates that no meaningful type exists.
+ * @group Types
*/
val NoType: Type
/** This constant is used as a special value denoting the empty prefix in a path dependent type.
* For instance `x.type` is represented as `SingleType(NoPrefix, <x>)`, where `<x>` stands for
* the symbol for `x`.
+ * @group Types
*/
val NoPrefix: Type
- /** The API of types
+ /** The API of types.
+ * The main source of information about types is the [[scala.reflect.api.Types]] page.
+ * @group API
*/
abstract class TypeApi {
/** The term symbol associated with the type, or `NoSymbol` for types
@@ -92,7 +157,8 @@ trait Types { self: Universe =>
/** Does this type conform to given type argument `that`? */
def <:< (that: Type): Boolean
- /** Is this type a weak subtype of that type? True also for numeric types, i.e. Int weak_<:< Long.
+ /** Does this type weakly conform to given type argument `that`, i.e., either conforms in terms of `<:<` or both are primitive number types
+ * that conform according to Section "Weak Conformance" in the spec. For example, Int weak_<:< Long.
*/
def weak_<:<(that: Type): Boolean
@@ -186,11 +252,14 @@ trait Types { self: Universe =>
* x.type
* }}}
* as well as [[ConstantType constant types]].
+ * @template
+ * @group Types
*/
type SingletonType >: Null <: Type
/** A tag that preserves the identity of the `SingletonType` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val SingletonTypeTag: ClassTag[SingletonType]
@@ -199,19 +268,25 @@ trait Types { self: Universe =>
* {{{
* C.this.type ThisType(C)
* }}}
+ * @template
+ * @group Types
*/
type ThisType >: Null <: AnyRef with SingletonType with ThisTypeApi
/** A tag that preserves the identity of the `ThisType` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val ThisTypeTag: ClassTag[ThisType]
- /** The constructor/deconstructor for `ThisType` instances. */
+ /** The constructor/deconstructor for `ThisType` instances.
+ * @group Extractors
+ */
val ThisType: ThisTypeExtractor
/** An extractor class to create and pattern match with syntax `ThisType(sym)`
* where `sym` is the class prefix of the this type.
+ * @group Extractors
*/
abstract class ThisTypeExtractor {
/**
@@ -221,8 +296,12 @@ trait Types { self: Universe =>
def unapply(tpe: ThisType): Option[Symbol]
}
- /** The API that all this types support */
+ /** The API that all this types support.
+ * The main source of information about types is the [[scala.reflect.api.Types]] page.
+ * @group API
+ */
trait ThisTypeApi extends TypeApi { this: ThisType =>
+ /** The underlying class symbol. */
val sym: Symbol
}
@@ -233,29 +312,41 @@ trait Types { self: Universe =>
* p.x.type SingleType(p.type, x)
* x.type SingleType(NoPrefix, x)
* }}}
+ * @template
+ * @group Types
*/
type SingleType >: Null <: AnyRef with SingletonType with SingleTypeApi
/** A tag that preserves the identity of the `SingleType` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val SingleTypeTag: ClassTag[SingleType]
- /** The constructor/deconstructor for `SingleType` instances. */
+ /** The constructor/deconstructor for `SingleType` instances.
+ * @group Extractors
+ */
val SingleType: SingleTypeExtractor
/** An extractor class to create and pattern match with syntax `SingleType(pre, sym)`
* Here, `pre` is the prefix of the single-type, and `sym` is the stable value symbol
* referred to by the single-type.
+ * @group Extractors
*/
abstract class SingleTypeExtractor {
def apply(pre: Type, sym: Symbol): Type // not SingleTypebecause of implementation details
def unapply(tpe: SingleType): Option[(Type, Symbol)]
}
- /** The API that all single types support */
+ /** The API that all single types support.
+ * The main source of information about types is the [[scala.reflect.api.Types]] page.
+ * @group API
+ */
trait SingleTypeApi extends TypeApi { this: SingleType =>
+ /** The type of the qualifier. */
val pre: Type
+
+ /** The underlying symbol. */
val sym: Symbol
}
/** The `SuperType` type is not directly written, but arises when `C.super` is used
@@ -266,27 +357,43 @@ trait Types { self: Universe =>
* Here, `thistpe` is the type of the corresponding this-type. For instance,
* in the type arising from C.super, the `thistpe` part would be `ThisType(C)`.
* `supertpe` is the type of the super class referred to by the `super`.
+ * @template
+ * @group Types
*/
type SuperType >: Null <: AnyRef with SingletonType with SuperTypeApi
/** A tag that preserves the identity of the `SuperType` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val SuperTypeTag: ClassTag[SuperType]
- /** The constructor/deconstructor for `SuperType` instances. */
+ /** The constructor/deconstructor for `SuperType` instances.
+ * @group Extractors
+ */
val SuperType: SuperTypeExtractor
/** An extractor class to create and pattern match with syntax `SingleType(thistpe, supertpe)`
+ * @group Extractors
*/
abstract class SuperTypeExtractor {
def apply(thistpe: Type, supertpe: Type): Type // not SuperTypebecause of implementation details
def unapply(tpe: SuperType): Option[(Type, Type)]
}
- /** The API that all super types support */
+ /** The API that all super types support.
+ * The main source of information about types is the [[scala.reflect.api.Types]] page.
+ * @group API
+ */
trait SuperTypeApi extends TypeApi { this: SuperType =>
+ /** The type of the qualifier.
+ * See the example for [[scala.reflect.api.Trees#SuperExtractor]].
+ */
val thistpe: Type
+
+ /** The type of the selector.
+ * See the example for [[scala.reflect.api.Trees#SuperExtractor]].
+ */
val supertpe: Type
}
/** The `ConstantType` type is not directly written in user programs, but arises as the type of a constant.
@@ -295,27 +402,37 @@ trait Types { self: Universe =>
* 1 ConstantType(Constant(1))
* "abc" ConstantType(Constant("abc"))
* }}}
+ * @template
+ * @group Types
*/
type ConstantType >: Null <: AnyRef with SingletonType with ConstantTypeApi
/** A tag that preserves the identity of the `ConstantType` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val ConstantTypeTag: ClassTag[ConstantType]
- /** The constructor/deconstructor for `ConstantType` instances. */
+ /** The constructor/deconstructor for `ConstantType` instances.
+ * @group Extractors
+ */
val ConstantType: ConstantTypeExtractor
/** An extractor class to create and pattern match with syntax `ConstantType(constant)`
* Here, `constant` is the constant value represented by the type.
+ * @group Extractors
*/
abstract class ConstantTypeExtractor {
def apply(value: Constant): ConstantType
def unapply(tpe: ConstantType): Option[Constant]
}
- /** The API that all constant types support */
+ /** The API that all constant types support.
+ * The main source of information about types is the [[scala.reflect.api.Types]] page.
+ * @group API
+ */
trait ConstantTypeApi extends TypeApi { this: ConstantType =>
+ /** The compile-time constant underlying this type. */
val value: Constant
}
@@ -329,40 +446,61 @@ trait Types { self: Universe =>
* p.C TypeRef(p.type, C, Nil)
* C TypeRef(NoPrefix, C, Nil)
* }}}
+ * @template
+ * @group Types
*/
type TypeRef >: Null <: AnyRef with Type with TypeRefApi
/** A tag that preserves the identity of the `TypeRef` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val TypeRefTag: ClassTag[TypeRef]
- /** The constructor/deconstructor for `TypeRef` instances. */
+ /** The constructor/deconstructor for `TypeRef` instances.
+ * @group Extractors
+ */
val TypeRef: TypeRefExtractor
/** An extractor class to create and pattern match with syntax `TypeRef(pre, sym, args)`
* Here, `pre` is the prefix of the type reference, `sym` is the symbol
* referred to by the type reference, and `args` is a possible empty list of
* type argumenrts.
+ * @group Extractors
*/
abstract class TypeRefExtractor {
def apply(pre: Type, sym: Symbol, args: List[Type]): Type // not TypeRefbecause of implementation details
def unapply(tpe: TypeRef): Option[(Type, Symbol, List[Type])]
}
- /** The API that all type refs support */
+ /** The API that all type refs support.
+ * The main source of information about types is the [[scala.reflect.api.Types]] page.
+ * @group API
+ */
trait TypeRefApi extends TypeApi { this: TypeRef =>
+ /** The prefix of the type reference.
+ * Is equal to `NoPrefix` if the prefix is not applicable.
+ */
val pre: Type
+
+ /** The underlying symbol of the type reference. */
val sym: Symbol
+
+ /** The arguments of the type reference.
+ * Is equal to `Nil` if the arguments are not provided.
+ */
val args: List[Type]
}
/** A subtype of Type representing refined types as well as `ClassInfo` signatures.
+ * @template
+ * @group Types
*/
type CompoundType >: Null <: AnyRef with Type
/** A tag that preserves the identity of the `CompoundType` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val CompoundTypeTag: ClassTag[CompoundType]
@@ -373,20 +511,26 @@ trait Types { self: Universe =>
* P_1 with ... with P_m RefinedType(List(P_1, ..., P_m), Scope())
* { D_1; ...; D_n} RefinedType(List(AnyRef), Scope(D_1, ..., D_n))
* }}}
+ * @template
+ * @group Types
*/
type RefinedType >: Null <: AnyRef with CompoundType with RefinedTypeApi
/** A tag that preserves the identity of the `RefinedType` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val RefinedTypeTag: ClassTag[RefinedType]
- /** The constructor/deconstructor for `RefinedType` instances. */
+ /** The constructor/deconstructor for `RefinedType` instances.
+ * @group Extractors
+ */
val RefinedType: RefinedTypeExtractor
/** An extractor class to create and pattern match with syntax `RefinedType(parents, decls)`
* Here, `parents` is the list of parent types of the class, and `decls` is the scope
* containing all declarations in the class.
+ * @group Extractors
*/
abstract class RefinedTypeExtractor {
def apply(parents: List[Type], decls: Scope): RefinedType
@@ -398,9 +542,15 @@ trait Types { self: Universe =>
def unapply(tpe: RefinedType): Option[(List[Type], Scope)]
}
- /** The API that all refined types support */
+ /** The API that all refined types support.
+ * The main source of information about types is the [[scala.reflect.api.Types]] page.
+ * @group API
+ */
trait RefinedTypeApi extends TypeApi { this: RefinedType =>
+ /** The superclasses of the type. */
val parents: List[Type]
+
+ /** The scope that holds the definitions comprising the type. */
val decls: Scope
}
@@ -413,44 +563,63 @@ trait Types { self: Universe =>
* {{{
* ClassInfo(List(P_1, ..., P_m), Scope(D_1, ..., D_n), C)
* }}}
+ * @template
+ * @group Types
*/
type ClassInfoType >: Null <: AnyRef with CompoundType with ClassInfoTypeApi
/** A tag that preserves the identity of the `ClassInfoType` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val ClassInfoTypeTag: ClassTag[ClassInfoType]
- /** The constructor/deconstructor for `ClassInfoType` instances. */
+ /** The constructor/deconstructor for `ClassInfoType` instances.
+ * @group Extractors
+ */
val ClassInfoType: ClassInfoTypeExtractor
/** An extractor class to create and pattern match with syntax `ClassInfo(parents, decls, clazz)`
* Here, `parents` is the list of parent types of the class, `decls` is the scope
* containing all declarations in the class, and `clazz` is the symbol of the class
* itself.
+ * @group Extractors
*/
abstract class ClassInfoTypeExtractor {
def apply(parents: List[Type], decls: Scope, typeSymbol: Symbol): ClassInfoType
def unapply(tpe: ClassInfoType): Option[(List[Type], Scope, Symbol)]
}
- /** The API that all class info types support */
+ /** The API that all class info types support.
+ * The main source of information about types is the [[scala.reflect.api.Types]] page.
+ * @group API
+ */
trait ClassInfoTypeApi extends TypeApi { this: ClassInfoType =>
+ /** The superclasses of the class type. */
val parents: List[Type]
+
+ /** The scope that holds the definitions comprising the class type. */
val decls: Scope
+
+ /** The symbol underlying the class type. */
val typeSymbol: Symbol
}
/** The `MethodType` type signature is used to indicate parameters and result type of a method
+ * @template
+ * @group Types
*/
type MethodType >: Null <: AnyRef with Type with MethodTypeApi
/** A tag that preserves the identity of the `MethodType` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val MethodTypeTag: ClassTag[MethodType]
- /** The constructor/deconstructor for `MethodType` instances. */
+ /** The constructor/deconstructor for `MethodType` instances.
+ * @group Extractors
+ */
val MethodType: MethodTypeExtractor
/** An extractor class to create and pattern match with syntax `MethodType(params, respte)`
@@ -466,128 +635,183 @@ trait Types { self: Universe =>
* def f: Int
* }}}
* its type is a `NullaryMethodType`.
+ * @group Extractors
*/
abstract class MethodTypeExtractor {
def apply(params: List[Symbol], resultType: Type): MethodType
def unapply(tpe: MethodType): Option[(List[Symbol], Type)]
}
- /** The API that all method types support */
+ /** The API that all method types support.
+ * The main source of information about types is the [[scala.reflect.api.Types]] page.
+ * @group API
+ */
trait MethodTypeApi extends TypeApi { this: MethodType =>
+ /** The symbols that correspond to the parameters of the method. */
val params: List[Symbol]
+
+ /** The result type of the method. */
val resultType: Type
}
/** The `NullaryMethodType` type signature is used for parameterless methods
* with declarations of the form `def foo: T`
+ * @template
+ * @group Types
*/
type NullaryMethodType >: Null <: AnyRef with Type with NullaryMethodTypeApi
/** A tag that preserves the identity of the `NullaryMethodType` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val NullaryMethodTypeTag: ClassTag[NullaryMethodType]
- /** The constructor/deconstructor for `NullaryMethodType` instances. */
+ /** The constructor/deconstructor for `NullaryMethodType` instances.
+ * @group Extractors
+ */
val NullaryMethodType: NullaryMethodTypeExtractor
/** An extractor class to create and pattern match with syntax `NullaryMethodType(resultType)`.
* Here, `resultType` is the result type of the parameterless method.
+ * @group Extractors
*/
abstract class NullaryMethodTypeExtractor {
def apply(resultType: Type): NullaryMethodType
def unapply(tpe: NullaryMethodType): Option[(Type)]
}
- /** The API that all nullary method types support */
+ /** The API that all nullary method types support.
+ * The main source of information about types is the [[scala.reflect.api.Types]] page.
+ * @group API
+ */
trait NullaryMethodTypeApi extends TypeApi { this: NullaryMethodType =>
+ /** The result type of the method. */
val resultType: Type
}
/** The `PolyType` type signature is used for polymorphic methods
* that have at least one type parameter.
+ * @template
+ * @group Types
*/
type PolyType >: Null <: AnyRef with Type with PolyTypeApi
/** A tag that preserves the identity of the `PolyType` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val PolyTypeTag: ClassTag[PolyType]
- /** The constructor/deconstructor for `PolyType` instances. */
+ /** The constructor/deconstructor for `PolyType` instances.
+ * @group Extractors
+ */
val PolyType: PolyTypeExtractor
/** An extractor class to create and pattern match with syntax `PolyType(typeParams, resultType)`.
* Here, `typeParams` are the type parameters of the method and `resultType`
* is the type signature following the type parameters.
+ * @group Extractors
*/
abstract class PolyTypeExtractor {
def apply(typeParams: List[Symbol], resultType: Type): PolyType
def unapply(tpe: PolyType): Option[(List[Symbol], Type)]
}
- /** The API that all polymorphic types support */
+ /** The API that all polymorphic types support.
+ * The main source of information about types is the [[scala.reflect.api.Types]] page.
+ * @group API
+ */
trait PolyTypeApi extends TypeApi { this: PolyType =>
+ /** The symbols corresponding to the type parameters. */
val typeParams: List[Symbol]
+
+ /** The underlying type. */
val resultType: Type
}
/** The `ExistentialType` type signature is used for existential types and
* wildcard types.
+ * @template
+ * @group Types
*/
type ExistentialType >: Null <: AnyRef with Type with ExistentialTypeApi
/** A tag that preserves the identity of the `ExistentialType` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val ExistentialTypeTag: ClassTag[ExistentialType]
- /** The constructor/deconstructor for `ExistentialType` instances. */
+ /** The constructor/deconstructor for `ExistentialType` instances.
+ * @group Extractors
+ */
val ExistentialType: ExistentialTypeExtractor
/** An extractor class to create and pattern match with syntax
* `ExistentialType(quantified, underlying)`.
* Here, `quantified` are the type variables bound by the existential type and `underlying`
* is the type that's existentially quantified.
+ * @group Extractors
*/
abstract class ExistentialTypeExtractor {
def apply(quantified: List[Symbol], underlying: Type): ExistentialType
def unapply(tpe: ExistentialType): Option[(List[Symbol], Type)]
}
- /** The API that all existential types support */
+ /** The API that all existential types support.
+ * The main source of information about types is the [[scala.reflect.api.Types]] page.
+ * @group API
+ */
trait ExistentialTypeApi extends TypeApi { this: ExistentialType =>
+ /** The symbols corresponding to the `forSome` clauses of the existential type. */
val quantified: List[Symbol]
+
+ /** The underlying type of the existential type. */
val underlying: Type
}
/** The `AnnotatedType` type signature is used for annotated types of the
* for `<type> @<annotation>`.
+ * @template
+ * @group Types
*/
type AnnotatedType >: Null <: AnyRef with Type with AnnotatedTypeApi
/** A tag that preserves the identity of the `AnnotatedType` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val AnnotatedTypeTag: ClassTag[AnnotatedType]
- /** The constructor/deconstructor for `AnnotatedType` instances. */
+ /** The constructor/deconstructor for `AnnotatedType` instances.
+ * @group Extractors
+ */
val AnnotatedType: AnnotatedTypeExtractor
/** An extractor class to create and pattern match with syntax
* `AnnotatedType(annotations, underlying, selfsym)`.
* Here, `annotations` are the annotations decorating the underlying type `underlying`.
* `selfSym` is a symbol representing the annotated type itself.
+ * @group Extractors
*/
abstract class AnnotatedTypeExtractor {
def apply(annotations: List[Annotation], underlying: Type, selfsym: Symbol): AnnotatedType
def unapply(tpe: AnnotatedType): Option[(List[Annotation], Type, Symbol)]
}
- /** The API that all annotated types support */
+ /** The API that all annotated types support.
+ * The main source of information about types is the [[scala.reflect.api.Types]] page.
+ * @group API
+ */
trait AnnotatedTypeApi extends TypeApi { this: AnnotatedType =>
+ /** The annotations. */
val annotations: List[Annotation]
+
+ /** The annotee. */
val underlying: Type
+
+ /** A symbol that represents the annotated type itself. */
val selfsym: Symbol
}
@@ -600,34 +824,51 @@ trait Types { self: Universe =>
* T >: L TypeBounds(L, Any)
* T <: U TypeBounds(Nothing, U)
* }}}
+ * @template
+ * @group Types
*/
type TypeBounds >: Null <: AnyRef with Type with TypeBoundsApi
/** A tag that preserves the identity of the `TypeBounds` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val TypeBoundsTag: ClassTag[TypeBounds]
- /** The constructor/deconstructor for `TypeBounds` instances. */
+ /** The constructor/deconstructor for `TypeBounds` instances.
+ * @group Extractors
+ */
val TypeBounds: TypeBoundsExtractor
/** An extractor class to create and pattern match with syntax `TypeBound(lower, upper)`
* Here, `lower` is the lower bound of the `TypeBounds` pair, and `upper` is
* the upper bound.
+ * @group Extractors
*/
abstract class TypeBoundsExtractor {
def apply(lo: Type, hi: Type): TypeBounds
def unapply(tpe: TypeBounds): Option[(Type, Type)]
}
- /** The API that all type bounds support */
+ /** The API that all type bounds support.
+ * The main source of information about types is the [[scala.reflect.api.Types]] page.
+ * @group API
+ */
trait TypeBoundsApi extends TypeApi { this: TypeBounds =>
+ /** The lower bound.
+ * Is equal to `definitions.NothingTpe` if not specified explicitly.
+ */
val lo: Type
+
+ /** The upper bound.
+ * Is equal to `definitions.AnyTpe` if not specified explicitly.
+ */
val hi: Type
}
/** An object representing an unknown type, used during type inference.
* If you see WildcardType outside of inference it is almost certainly a bug.
+ * @group Types
*/
val WildcardType: Type
@@ -640,55 +881,77 @@ trait Types { self: Universe =>
* the name of a method in the converted type, a HasMethodMatching
* type is created: a MethodType with parameters typed as
* BoundedWildcardTypes.
+ * @template
+ * @group Types
*/
type BoundedWildcardType >: Null <: AnyRef with Type with BoundedWildcardTypeApi
/** A tag that preserves the identity of the `BoundedWildcardType` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val BoundedWildcardTypeTag: ClassTag[BoundedWildcardType]
- /** The constructor/deconstructor for `BoundedWildcardType` instances. */
+ /** The constructor/deconstructor for `BoundedWildcardType` instances.
+ * @group Extractors
+ */
val BoundedWildcardType: BoundedWildcardTypeExtractor
/** An extractor class to create and pattern match with syntax `BoundedWildcardTypeExtractor(bounds)`
* with `bounds` denoting the type bounds.
+ * @group Extractors
*/
abstract class BoundedWildcardTypeExtractor {
def apply(bounds: TypeBounds): BoundedWildcardType
def unapply(tpe: BoundedWildcardType): Option[TypeBounds]
}
- /** The API that all this types support */
+ /** The API that all this types support.
+ * The main source of information about types is the [[scala.reflect.api.Types]] page.
+ * @group API
+ */
trait BoundedWildcardTypeApi extends TypeApi { this: BoundedWildcardType =>
+ /** Type bounds for the wildcard type. */
val bounds: TypeBounds
}
- /** The least upper bound of a list of types, as determined by `<:<`. */
+ /** The least upper bound of a list of types, as determined by `<:<`.
+ * @group TypeOps
+ */
def lub(xs: List[Type]): Type
- /** The greatest lower bound of a list of types, as determined by `<:<`. */
+ /** The greatest lower bound of a list of types, as determined by `<:<`.
+ * @group TypeOps
+ */
def glb(ts: List[Type]): Type
// Creators ---------------------------------------------------------------
// too useful and too non-trivial to be left out of public API
- /** The canonical creator for single-types */
+ /** The canonical creator for single-types
+ * @group TypeCreators
+ */
def singleType(pre: Type, sym: Symbol): Type
- /** the canonical creator for a refined type with a given scope */
+ /** the canonical creator for a refined type with a given scope
+ * @group TypeCreators
+ */
def refinedType(parents: List[Type], owner: Symbol, decls: Scope, pos: Position): Type
/** The canonical creator for a refined type with an initially empty scope.
+ * @group TypeCreators
*/
def refinedType(parents: List[Type], owner: Symbol): Type
/** The canonical creator for typerefs
+ * @group TypeCreators
*/
def typeRef(pre: Type, sym: Symbol, args: List[Type]): Type
/** A creator for intersection type where intersections of a single type are
- * replaced by the type itself. */
+ * replaced by the type itself.
+ * @group TypeCreators
+ */
def intersectionType(tps: List[Type]): Type
/** A creator for intersection type where intersections of a single type are
@@ -696,15 +959,19 @@ trait Types { self: Universe =>
*
* !!! Repeated parent classes are not merged - is this a bug in the
* comment or in the code?
+ * @group TypeCreators
*/
def intersectionType(tps: List[Type], owner: Symbol): Type
- /** A creator for type applications */
+ /** A creator for type applications
+ * @group Types
+ */
def appliedType(tycon: Type, args: List[Type]): Type
/** A creator for type parameterizations that strips empty type parameter lists.
* Use this factory method to indicate the type has kind * (it's a polymorphic value)
* until we start tracking explicit kinds equivalent to typeFun (except that the latter requires tparams nonEmpty).
+ * @group Types
*/
def polyType(tparams: List[Symbol], tpe: Type): Type
@@ -725,6 +992,7 @@ trait Types { self: Universe =>
* The abstraction drops all type parameters that are not directly or
* indirectly referenced by type `tpe1`. If there are no remaining type
* parameters, simply returns result type `tpe`.
+ * @group TypeCreators
*/
def existentialAbstraction(tparams: List[Symbol], tpe0: Type): Type
}
diff --git a/src/reflect/scala/reflect/api/Universe.scala b/src/reflect/scala/reflect/api/Universe.scala
index 7d0f6cf0d6..7d1f5c9df1 100644
--- a/src/reflect/scala/reflect/api/Universe.scala
+++ b/src/reflect/scala/reflect/api/Universe.scala
@@ -1,6 +1,58 @@
package scala.reflect
package api
+/**
+ * `Universe` provides a complete set of reflection operations which make it possible for one
+ * to reflectively inspect Scala type relations, such as membership or subtyping.
+ *
+ * [[scala.reflect.api.Universe]] has two specialized sub-universes for different scenarios.
+ * [[scala.reflect.api.JavaUniverse]] adds operations that link symbols and types to the underlying
+ * classes and runtime values of a JVM instance-- this can be thought of as the `Universe` that
+ * should be used for all typical use-cases of Scala reflection. [[scala.reflect.macros.Universe]]
+ * adds operations which allow macros to access selected compiler data structures and operations--
+ * this type of `Universe` should only ever exist within the implementation of a Scala macro.
+ *
+ * `Universe` can be thought of as the entry point to Scala reflection. It mixes-in, and thus provides
+ * an interface to the following main types:
+ *
+ * - [[scala.reflect.api.Types#Type Types]] represent types
+ * - [[scala.reflect.api.Symbols#Symbol Symbols]] represent definitions
+ * - [[scala.reflect.api.Trees#Tree Trees]] represent abstract syntax trees
+ * - [[scala.reflect.api.Names#Name Names]] represent term and type names
+ * - [[scala.reflect.api.Annotations#Annotation Annotations]] represent annotations
+ * - [[scala.reflect.api.Positions#Position Positions]] represent source positions of tree nodes
+ * - [[scala.reflect.api.FlagSets#FlagSet FlagSet]] represent sets of flags that apply to symbols and
+ * definition trees
+ * - [[scala.reflect.api.Constants#Constant Constants]] represent compile-time constants.
+ *
+ * To obtain a `Universe` to use with Scala runtime reflection, simply make sure to use or import
+ * `scala.reflect.runtime.universe._`
+ * {{{
+ * scala> import scala.reflect.runtime.universe._
+ * import scala.reflect.runtime.universe._
+ *
+ * scala> typeOf[List[Int]]
+ * res0: reflect.runtime.universe.Type = scala.List[Int]
+ *
+ * scala> typeOf[Either[String, Int]]
+ * res1: reflect.runtime.universe.Type = scala.Either[String,Int]
+ * }}}
+ *
+ * To obtain a `Universe` for use within a Scala macro, use [[scala.reflect.macros.Context#universe]]. For example:
+ * {{{
+ * def printf(format: String, params: Any*): Unit = macro impl
+ * def impl(c: Context)(format: c.Expr[String], params: c.Expr[Any]*): c.Expr[Unit] = {
+ * import c.universe._
+ * ...
+ * }
+ * }}}
+ *
+ * For more information about `Universe`s, see the [[http://docs.scala-lang.org/overviews/reflection/environment-universes-mirrors.html Reflection Guide: Universes]]
+ *
+ * @groupprio Universe -1
+ *
+ * @contentDiagram hideNodes "*Api"
+ */
abstract class Universe extends Symbols
with Types
with FlagSets
@@ -20,61 +72,20 @@ abstract class Universe extends Symbols
with Printers
with Importers
{
- /** Produce the abstract syntax tree representing the given Scala expression.
+ /** Use `refiy` to produce the abstract syntax tree representing a given Scala expression.
*
- * For example
+ * For example:
*
* {{{
* val five = reify{ 5 } // Literal(Constant(5))
- * reify{ 2 + 4 } // Apply( Select( Literal(Constant(2)), newTermName("$plus")), List( Literal(Constant(4)) ) )
- * reify{ five.splice + 4 } // Apply( Select( Literal(Constant(5)), newTermName("$plus")), List( Literal(Constant(4)) ) )
+ * reify{ 2 + 4 } // Apply( Select( Literal(Constant(2)), newTermName("\$plus")), List( Literal(Constant(4)) ) )
+ * reify{ five.splice + 4 } // Apply( Select( Literal(Constant(5)), newTermName("\$plus")), List( Literal(Constant(4)) ) )
* }}}
*
* The produced tree is path dependent on the Universe `reify` was called from.
*
- * Use [[scala.reflect.api.Exprs#Expr.splice]] to embed an existing expression into a reify call. Use [[Expr]] to turn a [[Tree]] into an expression that can be spliced.
- *
- * == Further info and implementation details ==
- *
- * `reify` is implemented as a macro, which given an expression, generates a tree that when compiled and executed produces the original tree.
- *
- * For instance in `reify{ x + 1 }` the macro `reify` receives the abstract syntax tree of `x + 1` as its argument, which is
- *
- * {{{
- * Apply(Select(Ident("x"), "+"), List(Literal(Constant(1))))
- * }}}
- *
- * and returns a tree, which produces the tree above, when compiled and executed. So in other terms, the refiy call expands to something like
- *
- * {{{
- * val $u: u.type = u // where u is a reference to the Universe that calls the reify
- * $u.Expr[Int]($u.Apply($u.Select($u.Ident($u.newFreeVar("x", <Int>, x), "+"), List($u.Literal($u.Constant(1))))))
- * }}}
- *
- * ------
- *
- * Reification performs expression splicing (when processing Expr.splice)
- * and type splicing (for every type T that has a TypeTag[T] implicit in scope):
- *
- * {{{
- * val two = mirror.reify(2) // Literal(Constant(2))
- * val four = mirror.reify(two.splice + two.splice) // Apply(Select(two.tree, newTermName("$plus")), List(two.tree))
- *
- * def macroImpl[T](c: Context) = {
- * ...
- * // T here is just a type parameter, so the tree produced by reify won't be of much use in a macro expansion
- * // however, if T were annotated with c.WeakTypeTag (which would declare an implicit parameter for macroImpl)
- * // then reification would substitute T with the TypeTree that was used in a TypeApply of this particular macro invocation
- * val factory = c.reify{ new Queryable[T] }
- * ...
- * }
- * }}}
- *
- * The transformation looks mostly straightforward, but it has its tricky parts:
- * - Reifier retains symbols and types defined outside the reified tree, however
- * locally defined entities get erased and replaced with their original trees
- * - Free variables are detected and wrapped in symbols of the type `FreeTermSymbol` or `FreeTypeSymbol`
- * - Mutable variables that are accessed from a local function are wrapped in refs
+ * Use [[scala.reflect.api.Exprs#Expr.splice]] to embed an existing expression into a `reify` call. Use [[Expr]] to turn a [[Tree]] into an expression that can be spliced.
+ * @group Universe
*/
// implementation is hardwired to `scala.reflect.reify.Taggers`
// using the mechanism implemented in `scala.tools.reflect.FastTrack`
diff --git a/src/reflect/scala/reflect/api/package.scala b/src/reflect/scala/reflect/api/package.scala
index 0b2a43936e..bd9c72a839 100644
--- a/src/reflect/scala/reflect/api/package.scala
+++ b/src/reflect/scala/reflect/api/package.scala
@@ -2,72 +2,35 @@ package scala.reflect
import scala.reflect.api.{Universe => ApiUniverse}
-/**
- * The main package of Scala's reflection library.
- *
- * The reflection library is structured according to the 'cake pattern'. The main layer
- * resides in package [[scala.reflect.api]] and defines an interface to the following main types:
- *
- * - [[scala.reflect.api.Types#Type Types]] represent types
- * - [[scala.reflect.api.Symbols#Symbol Symbols]] represent definitions
- * - [[scala.reflect.api.Trees#Tree Trees]] represent abstract syntax trees
- * - [[scala.reflect.api.Names#Name Names]] represent term and type names
- * - [[scala.reflect.api.Annotations#Annotation Annotations]] represent annotations
- * - [[scala.reflect.api.Positions#Position Positions]] represent source positions of tree nodes
- * - [[scala.reflect.api.FlagSets#FlagSet FlagSet]] represent sets of flags that apply to symbols and
- * definition trees
- * - [[scala.reflect.api.Constants#Constant Constants]] represent compile-time constants.
- *
- * Each of these types are defined in their own enclosing traits, which are ultimately all inherited by class
- * [[scala.reflect.api.Universe Universe]]. The main universe defines a minimal interface to the above types.
- * Universes that provide additional functionality such as deeper introspection or runtime code generation,
- * are defined in packages [[scala.reflect.api]] and `scala.tools.reflect`.
- *
- * The cake pattern employed here requires to write certain Scala idioms with more indirections that usual.
- * What follows is a description of these indirections, which will help to navigate the Scaladocs easily.
- *
- * For instance, consider the base type of all abstract syntax trees: [[scala.reflect.api.Trees#Tree]].
- * This type is not a class but is abstract and has an upper bound of [[scala.reflect.api.Trees#TreeApi]],
- * which is a class defining the minimal base interface for all trees.
- *
- * For a more interesting tree type, consider [[scala.reflect.api.Trees#If]] representing if-expressions.
- * It is defined next to a value `If` of type [[scala.reflect.api.Trees#IfExtractor]].
- * This value serves as the companion object defining a factory method `apply` and a corresponding `unapply`
- * for pattern matching.
- *
- * {{{
- * import scala.reflect.runtime.universe._
- * val cond = reify{ condition }.tree // <- just some tree representing a condition
- * val body = Literal(Constant(1))
- * val other = Literal(Constant(2))
- * val iftree = If(cond,body,other)
- * }}}
- *
- * is equivalent to
- *
- * {{{
- * import scala.reflect.runtime.universe._
- * val iftree = reify{ if( condition ) 1 else 2 }.tree
- * }}}
- *
- * and can be pattern matched as
- *
- * {{{
- * iftree match { case If(cond,body,other) => ... }
- * }}}
- *
- * Moreover, there is an implicit value [[scala.reflect.api.Trees#IfTag]] of type
- * `ClassTag[If]` that is used by the Scala compiler so that we can indeed pattern match on `If`:
- * {{{
- * iftree match { case _:If => ... }
- * }}}
- * Without the given implicit value, this pattern match would raise an "unchecked" warning at compile time
- * since `If` is an abstract type that gets erased at runtime. See [[scala.reflect.ClassTag]] for details.
- *
- * To summarize: each tree type `X` (and similarly for other types such as `Type` or `Symbol`) is represented
- * by an abstract type `X`, optionally together with a class `XApi` that defines `X`'s' interface.
- * `X`'s companion object, if it exists, is represented by a value `X` that is of type `XExtractor`.
- * Moreover, for each type `X`, there is a value `XTag` of type `ClassTag[X]` that allows to pattern match on `X`.
+/** The Scala Reflection API (located in scala-reflect.jar).
+ *
+ * In Scala 2.10.0, the Scala Reflection API and its implementation have an "experimental" status.
+ * This means that the API and the docs are not complete and can be changed in binary- and source-incompatible
+ * manner in 2.10.1. This also means that the implementation has some known issues.
+ *
+ * The following types are the backbone of the Scala Reflection API, and serve as a good starting point
+ * for information about Scala Reflection:
+ *
+ * - [[scala.reflect.api.Symbols]]
+ * - [[scala.reflect.api.Types]]
+ * - [[scala.reflect.api.Mirrors]]
+ * - [[scala.reflect.api.Universe]]
+ *
+ * For more information about Scala Reflection, see the
+ * [[http://docs.scala-lang.org/overviews/reflection/overview.html Reflection Guide]]
+ *
+ * @groupprio API 9
+ * @groupprio Extractors 10
+ * @groupprio Tags 11
+ * @groupdesc API The methods available for each reflection entity, without the implementation. Since the
+ * reflection entities are later overridden by runtime reflection and macros, their API
+ * counterparts guarantee a minimum set of methods that are implemented.
+ * @groupdesc Extractors Extractors provide the machinery necessary to allow pattern matching and construction of
+ * reflection entities that is similar to case classes, although the entities are only abstract
+ * types that are later overridden.
+ * @groupdesc Tags Implicit values that provide [[scala.reflect.ClassTag `ClassTags`]] for the reflection
+ * classes. These are abstract in the interface but are later filled in to provide ClassTags
+ * for the either the runtime reflection or macros entities, depending on the use.
*/
package object api {
diff --git a/src/reflect/scala/reflect/internal/util/Position.scala b/src/reflect/scala/reflect/internal/util/Position.scala
index d4225bcff5..5456d66584 100644
--- a/src/reflect/scala/reflect/internal/util/Position.scala
+++ b/src/reflect/scala/reflect/internal/util/Position.scala
@@ -35,6 +35,50 @@ object Position {
}
}
+/** The Position class and its subclasses represent positions of ASTs and symbols.
+ * Except for NoPosition and FakePos, every position refers to a SourceFile
+ * and to an offset in the sourcefile (its `point`). For batch compilation,
+ * that's all. For interactive IDE's there are also RangePositions
+ * and TransparentPositions. A RangePosition indicates a start and an end
+ * in addition to its point. TransparentPositions are a subclass of RangePositions.
+ * Range positions that are not transparent are called opaque.
+ * Trees with RangePositions need to satisfy the following invariants.
+ *
+ * INV1: A tree with an offset position never contains a child
+ * with a range position
+ * INV2: If the child of a tree with a range position also has a range position,
+ * then the child's range is contained in the parent's range.
+ * INV3: Opaque range positions of children of the same node are non-overlapping
+ * (this means their overlap is at most a single point).
+ *
+ * The following tests are useful on positions:
+ *
+ * pos.isDefined true if position is not a NoPosition nor a FakePosition
+ * pos.isRange true if position is a range
+ * pos.isOpaqueRange true if position is an opaque range
+ *
+ * The following accessor methods are provided:
+ *
+ * pos.source The source file of the position, which must be defined
+ * pos.point The offset of the position's point, which must be defined
+ * pos.start The start of the position, which must be a range
+ * pos.end The end of the position, which must be a range
+ *
+ * There are also convenience methods, such as
+ *
+ * pos.startOrPoint
+ * pos.endOrPoint
+ * pos.pointOrElse(default)
+ *
+ * These are less strict about the kind of position on which they can be applied.
+ *
+ * The following conversion methods are often used:
+ *
+ * pos.focus converts a range position to an offset position, keeping its point;
+ * returns all other positions unchanged.
+ * pos.makeTransparent converts an opaque range position into a transparent one.
+ * returns all other positions unchanged.
+ */
abstract class Position extends scala.reflect.api.Position { self =>
type Pos = Position
diff --git a/src/reflect/scala/reflect/macros/Aliases.scala b/src/reflect/scala/reflect/macros/Aliases.scala
index 754335d50d..7f7ab66848 100644
--- a/src/reflect/scala/reflect/macros/Aliases.scala
+++ b/src/reflect/scala/reflect/macros/Aliases.scala
@@ -1,33 +1,109 @@
package scala.reflect
package macros
+/** A slice of [[scala.reflect.macros.Context the Scala macros context]] that defines shorthands for the
+ * most frequently used types and functions of the underlying compiler universe.
+ */
trait Aliases {
self: Context =>
+ /** The type of symbols representing declarations. */
type Symbol = universe.Symbol
+
+ /** The type of Scala types, and also Scala type signatures.
+ * (No difference is internally made between the two).
+ */
type Type = universe.Type
+
+ /** The abstract type of names. */
type Name = universe.Name
+
+ /** The abstract type of names representing terms. */
type TermName = universe.TermName
+
+ /** The abstract type of names representing types. */
type TypeName = universe.TypeName
+
+ /** The type of Scala abstract syntax trees. */
type Tree = universe.Tree
+
+ /** Defines a universe-specific notion of positions. */
type Position = universe.Position
+
+ /** The base type of all scopes. */
type Scope = universe.Scope
+
+ /** The type of tree modifiers. */
type Modifiers = universe.Modifiers
+
+ /** The type of compilation runs. */
type Run = universe.Run
+
+ /** The type of compilation units. */
type CompilationUnit = universe.CompilationUnit
+ /** Expr wraps an abstract syntax tree and tags it with its type. */
type Expr[+T] = universe.Expr[T]
+
+ /** Constructor/Extractor for `Expr`. */
val Expr = universe.Expr
+
+ /** A shorthand to create an expr.
+ *
+ * Unlike the conventional expr factory, which requires a [[scala.reflect.api.TreeCreator]],
+ * this one accepts a regular tree, but the resulting exprs are unable of being migrated
+ * to other universes/mirrors (the functionality normally not needed for macros, since there is
+ * only one compile-time universe and only one compile-time mirror).
+ */
def Expr[T: WeakTypeTag](tree: Tree): Expr[T]
+ /** The type of weak type tags. */
type WeakTypeTag[T] = universe.WeakTypeTag[T]
+
+ /** The type of type tags. */
type TypeTag[T] = universe.TypeTag[T]
+
+ /** Constructor/Extractor for `WeakTypeTag`. */
val WeakTypeTag = universe.WeakTypeTag
+
+ /** Constructor/Extractor for `TypeTag`. */
val TypeTag = universe.TypeTag
+
+ /** A shorthand to create a weak type tag.
+ *
+ * Unlike the conventional type tag factory, which requires a [[scala.reflect.api.TypeCreator]],
+ * this one accepts a regular type, but the resulting type tags are unable of being migrated
+ * to other universes/mirrors (the functionality normally not needed for macros, since there is
+ * only one compile-time universe and only one compile-time mirror).
+ */
def WeakTypeTag[T](tpe: Type): WeakTypeTag[T]
+
+ /** A shorthand to create a type tag.
+ *
+ * Unlike the conventional type tag factory, which requires a [[scala.reflect.api.TypeCreator]],
+ * this one accepts a regular type, but the resulting type tags are unable of being migrated
+ * to other universes/mirrors (the functionality normally not needed for macros, since there is
+ * only one compile-time universe and only one compile-time mirror).
+ */
def TypeTag[T](tpe: Type): TypeTag[T]
+
+ /**
+ * Shortcut for `implicitly[WeakTypeTag[T]]`
+ */
def weakTypeTag[T](implicit attag: WeakTypeTag[T]) = attag
+
+ /**
+ * Shortcut for `implicitly[TypeTag[T]]`
+ */
def typeTag[T](implicit ttag: TypeTag[T]) = ttag
+
+ /**
+ * Shortcut for `implicitly[WeakTypeTag[T]].tpe`
+ */
def weakTypeOf[T](implicit attag: WeakTypeTag[T]): Type = attag.tpe
+
+ /**
+ * Shortcut for `implicitly[TypeTag[T]].tpe`
+ */
def typeOf[T](implicit ttag: TypeTag[T]): Type = ttag.tpe
}
diff --git a/src/reflect/scala/reflect/macros/Context.scala b/src/reflect/scala/reflect/macros/Context.scala
index 7a365ed37b..1f6e97adbc 100644
--- a/src/reflect/scala/reflect/macros/Context.scala
+++ b/src/reflect/scala/reflect/macros/Context.scala
@@ -5,6 +5,25 @@ package macros
// the most lightweight context should just expose the stuff from the SIP
// the full context should include all traits from scala.reflect.macros (and probably reside in scala-compiler.jar)
+/** The Scala macros context.
+ *
+ * See [[scala.reflect.macros.package the overview page]] for a description of how macros work. This documentation
+ * entry provides information on the API available to macro writers.
+ *
+ * A macro context wraps a compiler universe exposed in `universe` and having type [[scala.reflect.macros.Universe]].
+ * This type is a refinement over the generic reflection API provided in [[scala.reflect.api.Universe]]. The
+ * extended Universe provides mutability for reflection artifacts (e.g. macros can change types of compiler trees,
+ * add annotation to symbols representing definitions, etc) and exposes some internal compiler functionality
+ * such as `Symbol.deSkolemize` or `Tree.attachments`.
+ *
+ * Another fundamental part of a macro context is `macroApplication`, which provides access to the tree undergoing
+ * macro expansion. Parts of this tree can be found in arguments of the corresponding macro implementations and
+ * in `prefix`, but `macroApplication` gives the full picture.
+ *
+ * Other than that, macro contexts provide facilities for typechecking, exploring the compiler's symbol table and
+ * enclosing trees and compilation units, evaluating trees, logging warnings/errors and much more.
+ * Refer to the documentation of top-level traits in this package to learn the details.
+ */
trait Context extends Aliases
with Enclosures
with Names
@@ -16,15 +35,53 @@ trait Context extends Aliases
with Evals
with ExprUtils {
- /** The compile-time universe */
+ /** The compile-time universe. */
val universe: Universe
- /** The mirror of the compile-time universe */
+ /** The mirror of the compile-time universe. */
val mirror: universe.Mirror
- /** The type of the prefix tree from which the macro is selected */
+ /** The type of the prefix tree from which the macro is selected.
+ * See the documentation entry for `prefix` for an example.
+ */
type PrefixType
- /** The prefix tree from which the macro is selected */
+ /** The prefix tree from which the macro is selected.
+ *
+ * For a example, for a macro `filter` defined as an instance method on a collection `Coll`,
+ * `prefix` represents an equivalent of `this` for normal instance methods:
+ *
+ * {{{
+ * scala> class Coll[T] {
+ * | def filter(p: T => Boolean): Coll[T] = macro M.filter[T]
+ * | }; object M {
+ * | def filter[T](c: Context { type PrefixType = Coll[T] })
+ * | (p: c.Expr[T => Boolean]): c.Expr[Coll[T]] =
+ * | {
+ * | println(c.prefix.tree)
+ * | c.prefix
+ * | }
+ * | }
+ * defined class Coll
+ * defined module Macros
+ *
+ * scala> new Coll[Int]().filter(_ % 2 == 0)
+ * new Coll[Int]()
+ * res0: Coll[Int] = ...
+ *
+ * scala> val x = new Coll[String]()
+ * x: Coll[String] = ...
+ *
+ * scala> x.filter(_ != "")
+ * \$line11.\$read.\$iw.\$iw.\$iw.\$iw.\$iw.\$iw.\$iw.\$iw.\$iw.\$iw.\$iw.\$iw.x
+ * res1 @ 35563b4b: x.type = ...
+ * }}}
+ *
+ * Note how the value of `prefix` changes depending on the qualifier of the macro call
+ * (i.e. the expression that is at the left-hand side of the dot).
+ *
+ * Another noteworthy thing about the snippet above is the `Context { type PrefixType = Coll[T] }`
+ * type that is used to stress that the macro implementation works with prefixes of type `Coll[T]`.
+ */
val prefix: Expr[PrefixType]
}
diff --git a/src/reflect/scala/reflect/macros/Enclosures.scala b/src/reflect/scala/reflect/macros/Enclosures.scala
index 218cf6ebb3..41d6af94e3 100644
--- a/src/reflect/scala/reflect/macros/Enclosures.scala
+++ b/src/reflect/scala/reflect/macros/Enclosures.scala
@@ -1,6 +1,11 @@
package scala.reflect
package macros
+/** A slice of [[scala.reflect.macros.Context the Scala macros context]] that exposes
+ * enclosing trees (method, class, compilation unit and currently compiled application),
+ * the enclosing position of the macro expansion, as well as macros and implicits
+ * that are currently in-flight.
+ */
trait Enclosures {
self: Context =>
diff --git a/src/reflect/scala/reflect/macros/Evals.scala b/src/reflect/scala/reflect/macros/Evals.scala
index 3837d749da..6aab3d5b02 100644
--- a/src/reflect/scala/reflect/macros/Evals.scala
+++ b/src/reflect/scala/reflect/macros/Evals.scala
@@ -1,9 +1,54 @@
package scala.reflect
package macros
+/** A slice of [[scala.reflect.macros.Context the Scala macros context]] that provides
+ * a facility to evaluate trees.
+ */
trait Evals {
self: Context =>
- /** .. */
+ /** Takes a typed wrapper for a tree of type `T` and evaluates it to a value of type `T`.
+ *
+ * Can be used to perform compile-time computations on macro arguments to the extent
+ * permitted by the shape of the arguments.
+ *
+ * Known issues: because of [[https://issues.scala-lang.org/browse/SI-5748 https://issues.scala-lang.org/browse/SI-5748]]
+ * trees being evaluated first need to undergo `resetAllAttrs`. Resetting symbols and types
+ * mutates the tree in place, therefore the conventional approach is to `duplicate` the tree first.
+ *
+ * {{{
+ * scala> def impl(c: Context)(x: c.Expr[String]) = {
+ * | val x1 = c.Expr[String](c.resetAllAttrs(x.tree.duplicate))
+ * | println(s"compile-time value is: \${c.eval(x1)}")
+ * | x
+ * | }
+ * impl: (c: Context)(x: c.Expr[String])c.Expr[String]
+ *
+ * scala> def test(x: String) = macro impl
+ * test: (x: String)String
+ *
+ * scala> test("x")
+ * compile-time value is: x
+ * res0: String = x
+ *
+ * scala> test("x" + "y")
+ * compile-time value is: xy
+ * res1: String = xy
+ *
+ * scala> val x = "x"
+ * x: String = x
+ *
+ * scala> test(x + "y")
+ * compile-time value is: xy
+ * res2: String = xy
+ *
+ * scala> { val x = "x"; test(x + "y") }
+ * error: exception during macro expansion:
+ * scala.tools.reflect.ToolBoxError: reflective compilation failed
+ * }}}
+ *
+ * Note that in the last case evaluation has failed, because the argument of a macro
+ * refers to a runtime value `x`, which is unknown at compile time.
+ */
def eval[T](expr: Expr[T]): T
} \ No newline at end of file
diff --git a/src/reflect/scala/reflect/macros/ExprUtils.scala b/src/reflect/scala/reflect/macros/ExprUtils.scala
index adcdc78c78..a9acc61735 100644
--- a/src/reflect/scala/reflect/macros/ExprUtils.scala
+++ b/src/reflect/scala/reflect/macros/ExprUtils.scala
@@ -1,32 +1,48 @@
package scala.reflect
package macros
+/** A slice of [[scala.reflect.macros.Context the Scala macros context]] that defines shorthands for the
+ * most common `Expr`-creating functions.
+ */
trait ExprUtils {
self: Context =>
+ /** Shorthand for `Literal(Constant(null))` in the underlying `universe`. */
def literalNull: Expr[Null]
+ /** Shorthand for `Literal(Constant(()))` in the underlying `universe`. */
def literalUnit: Expr[Unit]
+ /** Shorthand for `Literal(Constant(true))` in the underlying `universe`. */
def literalTrue: Expr[Boolean]
+ /** Shorthand for `Literal(Constant(false))` in the underlying `universe`. */
def literalFalse: Expr[Boolean]
+ /** Shorthand for `Literal(Constant(x: Boolean))` in the underlying `universe`. */
def literal(x: Boolean): Expr[Boolean]
+ /** Shorthand for `Literal(Constant(x: Byte))` in the underlying `universe`. */
def literal(x: Byte): Expr[Byte]
+ /** Shorthand for `Literal(Constant(x: Short))` in the underlying `universe`. */
def literal(x: Short): Expr[Short]
+ /** Shorthand for `Literal(Constant(x: Int))` in the underlying `universe`. */
def literal(x: Int): Expr[Int]
+ /** Shorthand for `Literal(Constant(x: Long))` in the underlying `universe`. */
def literal(x: Long): Expr[Long]
+ /** Shorthand for `Literal(Constant(x: Float))` in the underlying `universe`. */
def literal(x: Float): Expr[Float]
+ /** Shorthand for `Literal(Constant(x: Double))` in the underlying `universe`. */
def literal(x: Double): Expr[Double]
+ /** Shorthand for `Literal(Constant(x: String))` in the underlying `universe`. */
def literal(x: String): Expr[String]
+ /** Shorthand for `Literal(Constant(x: Char))` in the underlying `universe`. */
def literal(x: Char): Expr[Char]
}
diff --git a/src/reflect/scala/reflect/macros/FrontEnds.scala b/src/reflect/scala/reflect/macros/FrontEnds.scala
index e6b67cfc87..8c47202342 100644
--- a/src/reflect/scala/reflect/macros/FrontEnds.scala
+++ b/src/reflect/scala/reflect/macros/FrontEnds.scala
@@ -1,30 +1,44 @@
package scala.reflect
package macros
+/** A slice of [[scala.reflect.macros.Context the Scala macros context]] that
+ * provides facilities to communicate with the compiler's front end
+ * (emit warnings, errors and other sorts of messages).
+ */
trait FrontEnds {
self: Context =>
/** For sending a message which should not be labeled as a warning/error,
* but also shouldn't require -verbose to be visible.
- * Use ``enclosingPosition'' if you're in doubt what position to pass to ``pos''.
+ * Use `enclosingPosition` if you're in doubt what position to pass to `pos`.
*/
def echo(pos: Position, msg: String): Unit
- /** Informational messages, suppressed unless -verbose or force=true.
- * Use ``enclosingPosition'' if you're in doubt what position to pass to ``pos''.
+ /** Emits an informational message, suppressed unless `-verbose` or `force=true`.
+ * Use `enclosingPosition` if you're in doubt what position to pass to `pos`.
*/
def info(pos: Position, msg: String, force: Boolean): Unit
- /** Warnings and errors.
- * Use ``enclosingPosition'' if you're in doubt what position to pass to ``pos''.
+ /** Does the compilation session have any warnings?
*/
def hasWarnings: Boolean
- def hasErrors: Boolean
+
+ /** Emits a warning.
+ * Use `enclosingPosition` if you're in doubt what position to pass to `pos`.
+ */
def warning(pos: Position, msg: String): Unit
+
+ /** Does the compilation session have any errors?
+ */
+ def hasErrors: Boolean
+
+ /** Emits a compilation error.
+ * Use `enclosingPosition` if you're in doubt what position to pass to `pos`.
+ */
def error(pos: Position, msg: String): Unit
/** Abruptly terminates current macro expansion leaving a note about what happened.
- * Use ``enclosingPosition'' if you're in doubt what position to pass to ``pos''.
+ * Use `enclosingPosition` if you're in doubt what position to pass to `pos`.
*/
def abort(pos: Position, msg: String): Nothing
} \ No newline at end of file
diff --git a/src/reflect/scala/reflect/macros/Infrastructure.scala b/src/reflect/scala/reflect/macros/Infrastructure.scala
index a1ef1c87a3..2f3b8e8d19 100644
--- a/src/reflect/scala/reflect/macros/Infrastructure.scala
+++ b/src/reflect/scala/reflect/macros/Infrastructure.scala
@@ -1,6 +1,9 @@
package scala.reflect
package macros
+/** A slice of [[scala.reflect.macros.Context the Scala macros context]] that
+ * provides facilities to communicate with the compiler's infrastructure.
+ */
trait Infrastructure {
self: Context =>
diff --git a/src/reflect/scala/reflect/macros/Names.scala b/src/reflect/scala/reflect/macros/Names.scala
index fab9bbbca5..20e750b225 100644
--- a/src/reflect/scala/reflect/macros/Names.scala
+++ b/src/reflect/scala/reflect/macros/Names.scala
@@ -1,15 +1,20 @@
package scala.reflect
package macros
+/** A slice of [[scala.reflect.macros.Context the Scala macros context]] that
+ * provides functions that generate unique names.
+ */
trait Names {
self: Context =>
- /** Creates a fresh string */
+ /** Creates a unique string. */
def fresh(): String
- /** Creates a fresh string from the provided string */
+ /** Creates a unique string having a given prefix. */
def fresh(name: String): String
- /** Creates a fresh name from the provided name */
+ /** Creates a unique name having a given name as a prefix and
+ * having the same flavor (term name or type name) as the given name.
+ */
def fresh[NameType <: Name](name: NameType): NameType
}
diff --git a/src/reflect/scala/reflect/macros/Parsers.scala b/src/reflect/scala/reflect/macros/Parsers.scala
index d3aabcff0d..bf73c36b1b 100644
--- a/src/reflect/scala/reflect/macros/Parsers.scala
+++ b/src/reflect/scala/reflect/macros/Parsers.scala
@@ -1,15 +1,19 @@
package scala.reflect
package macros
+/** A slice of [[scala.reflect.macros.Context the Scala macros context]] that
+ * exposes functions to parse strings with Scala code into trees.
+ */
trait Parsers {
self: Context =>
- /** .. */
- // todo. distinguish between parsing an expression and parsing arbitrary code
- // for example, parsing in expression mode will fail on packages
+ /** Parses a string with a Scala expression into an abstract syntax tree.
+ * Only works for expressions, i.e. parsing a package declaration will fail.
+ * @throws [[scala.reflect.macros.ParseException]]
+ */
def parse(code: String): Tree
}
-/** Indicates an error during [[scala.reflect.macros.Parsers#Parse]].
+/** Indicates an error during [[scala.reflect.macros.Parsers#parse]].
*/
case class ParseException(val pos: scala.reflect.api.Position, val msg: String) extends Exception(msg)
diff --git a/src/reflect/scala/reflect/macros/Reifiers.scala b/src/reflect/scala/reflect/macros/Reifiers.scala
index 0022a488b9..d7ee30c7d9 100644
--- a/src/reflect/scala/reflect/macros/Reifiers.scala
+++ b/src/reflect/scala/reflect/macros/Reifiers.scala
@@ -1,6 +1,9 @@
package scala.reflect
package macros
+/** A slice of [[scala.reflect.macros.Context the Scala macros context]] that
+ * exposes functions to save reflection artifacts for runtime.
+ */
trait Reifiers {
self: Context =>
diff --git a/src/reflect/scala/reflect/macros/TreeBuilder.scala b/src/reflect/scala/reflect/macros/TreeBuilder.scala
index 5f18ab9ee8..727387c5af 100644
--- a/src/reflect/scala/reflect/macros/TreeBuilder.scala
+++ b/src/reflect/scala/reflect/macros/TreeBuilder.scala
@@ -1,6 +1,9 @@
package scala.reflect
package macros
+/** A helper available in [[scala.reflect.macros.Universe]] that defines shorthands for the
+ * most common tree-creating functions.
+ */
abstract class TreeBuilder {
val global: Universe
@@ -46,12 +49,26 @@ abstract class TreeBuilder {
* @return the newly created trees.
*/
def mkMethodCall(receiver: Symbol, methodName: Name, targs: List[Type], args: List[Tree]): Tree
+
+ /** TODO how to refer to the main `mkMethodCall`? */
def mkMethodCall(method: Symbol, targs: List[Type], args: List[Tree]): Tree
+
+ /** TODO how to refer to the main `mkMethodCall`? */
def mkMethodCall(method: Symbol, args: List[Tree]): Tree
+
+ /** TODO how to refer to the main `mkMethodCall`? */
def mkMethodCall(target: Tree, args: List[Tree]): Tree
+
+ /** TODO how to refer to the main `mkMethodCall`? */
def mkMethodCall(receiver: Symbol, methodName: Name, args: List[Tree]): Tree
+
+ /** TODO how to refer to the main `mkMethodCall`? */
def mkMethodCall(receiver: Tree, method: Symbol, targs: List[Type], args: List[Tree]): Tree
+
+ /** TODO how to refer to the main `mkMethodCall`? */
def mkMethodCall(target: Tree, targs: List[Type], args: List[Tree]): Tree
+
+ /** TODO how to refer to the main `mkMethodCall`? */
def mkNullaryCall(method: Symbol, targs: List[Type]): Tree
/** A tree that refers to the runtime reflexive universe, ``scala.reflect.runtime.universe''. */
diff --git a/src/reflect/scala/reflect/macros/Typers.scala b/src/reflect/scala/reflect/macros/Typers.scala
index 9c4854f89f..016a08bd01 100644
--- a/src/reflect/scala/reflect/macros/Typers.scala
+++ b/src/reflect/scala/reflect/macros/Typers.scala
@@ -1,6 +1,9 @@
package scala.reflect
package macros
+/** A slice of [[scala.reflect.macros.Context the Scala macros context]] that
+ * partially exposes the type checker to macro writers.
+ */
trait Typers {
self: Context =>
diff --git a/src/reflect/scala/reflect/macros/Universe.scala b/src/reflect/scala/reflect/macros/Universe.scala
index 3e38691d85..86bc37b4c9 100644
--- a/src/reflect/scala/reflect/macros/Universe.scala
+++ b/src/reflect/scala/reflect/macros/Universe.scala
@@ -1,69 +1,125 @@
package scala.reflect
package macros
+/** The refinement of [[scala.reflect.api.Universe]] for the use by macro writers.
+ *
+ * This universe provides mutability for reflection artifacts (e.g. macros can change types of compiler trees,
+ * add annotation to symbols representing definitions, etc) and exposes some internal compiler functionality
+ * such as `Symbol.deSkolemize` or `Tree.attachments`.
+ * @groupname Macros Macro Specific Additions
+ * @groupprio Macros -1
+ *
+ * @contentDiagram hideNodes "*Api"
+ */
abstract class Universe extends scala.reflect.api.Universe {
+ /** A factory that encapsulates common tree-building functions.
+ * @group Macros
+ */
val treeBuild: TreeBuilder { val global: Universe.this.type }
+ /** The API of reflection artifacts that support [[scala.reflect.macros.Attachments]].
+ * These artifacts are trees and symbols.
+ * @group Macros
+ */
trait AttachableApi {
- /** ... */
+ /** The attachment of the reflection artifact. */
def attachments: Attachments { type Pos = Position }
- /** ... */
+ /** Updates the attachment with the payload slot of T added/updated with the provided value.
+ * Replaces an existing payload of the same type, if exists.
+ * Returns the reflection artifact itself.
+ */
def updateAttachment[T: ClassTag](attachment: T): AttachableApi.this.type
- /** ... */
+ /** Update the attachment with the payload of the given class type `T` removed.
+ * Returns the reflection artifact itself.
+ */
def removeAttachment[T: ClassTag]: AttachableApi.this.type
}
// Symbol extensions ---------------------------------------------------------------
+ /** The `Symbol` API is extended for macros: See [[SymbolContextApi]] for details.
+ *
+ * @group Macros
+ */
override type Symbol >: Null <: SymbolContextApi
/** The extended API of symbols that's supported in macro context universes
+ * @group API
*/
trait SymbolContextApi extends SymbolApi with AttachableApi { self: Symbol =>
+ /** If this symbol is a skolem, its corresponding type parameter, otherwise the symbol itself.
+ *
+ * [[https://groups.google.com/forum/#!msg/scala-internals/0j8laVNTQsI/kRXMF_c8bGsJ To quote Martin Odersky]],
+ * skolems are synthetic type "constants" that are copies of existentially bound or universally
+ * bound type variables. E.g. if one is inside the right-hand side of a method:
+ *
+ * {{{
+ * def foo[T](x: T) = ... foo[List[T]]....
+ * }}}
+ *
+ * the skolem named `T` refers to the unknown type instance of `T` when `foo` is called. It needs to be different
+ * from the type parameter because in a recursive call as in the `foo[List[T]]` above the type parameter gets
+ * substituted with `List[T]`, but the ''type skolem'' stays what it is.
+ *
+ * The other form of skolem is an ''existential skolem''. Say one has a function
+ *
+ * {{{
+ * def bar(xs: List[T] forSome { type T }) = xs.head
+ * }}}
+ *
+ * then each occurrence of `xs` on the right will have type `List[T']` where `T'` is a fresh copy of `T`.
+ */
def deSkolemize: Symbol
- /** The position of this symbol
- */
+ /** The position of this symbol. */
def pos: Position
+ /** Sets the `typeSignature` of the symbol. */
def setTypeSignature(tpe: Type): Symbol
+ /** Sets the `annotations` of the symbol. */
def setAnnotations(annots: Annotation*): Symbol
+ /** Sets the `name` of the symbol. */
def setName(name: Name): Symbol
+ /** Sets the `privateWithin` of the symbol. */
def setPrivateWithin(sym: Symbol): Symbol
}
// Tree extensions ---------------------------------------------------------------
+ /** The `Tree` API is extended for macros: See [[TreeContextApi]] for details.
+ *
+ * @group Macros
+ */
override type Tree >: Null <: TreeContextApi
/** The extended API of trees that's supported in macro context universes
+ * @group API
*/
trait TreeContextApi extends TreeApi with AttachableApi { self: Tree =>
- /** ... */
+ /** Sets the `pos` of the tree. Returns `Unit`. */
def pos_=(pos: Position): Unit
- /** ... */
+ /** Sets the `pos` of the tree. Returns the tree itself. */
def setPos(newpos: Position): Tree
- /** ... */
+ /** Sets the `tpe` of the tree. Returns `Unit`. */
def tpe_=(t: Type): Unit
- /** Set tpe to give `tp` and return this.
- */
+ /** Sets the `tpe` of the tree. Returns the tree itself. */
def setType(tp: Type): Tree
/** Like `setType`, but if this is a previously empty TypeTree that
* fact is remembered so that resetAllAttrs will snap back.
*
- * @PP: Attempting to elaborate on the above, I find: If defineType
+ * \@PP: Attempting to elaborate on the above, I find: If defineType
* is called on a TypeTree whose type field is null or NoType,
* this is recorded as "wasEmpty = true". That value is used in
* ResetAttrsTraverser, which nulls out the type field of TypeTrees
@@ -79,55 +135,72 @@ abstract class Universe extends scala.reflect.api.Universe {
*/
def defineType(tp: Type): Tree
- /** ... */
+ /** Sets the `symbol` of the tree. Returns `Unit`. */
def symbol_=(sym: Symbol): Unit
- /** ... */
+ /** Sets the `symbol` of the tree. Returns the tree itself. */
def setSymbol(sym: Symbol): Tree
}
+ /** @inheritdoc */
override type SymTree >: Null <: Tree with SymTreeContextApi
/** The extended API of sym trees that's supported in macro context universes
+ * @group API
*/
trait SymTreeContextApi extends SymTreeApi { this: SymTree =>
+ /** Sets the `symbol` field of the sym tree. */
var symbol: Symbol
}
+ /** @inheritdoc */
override type TypeTree >: Null <: TypTree with TypeTreeContextApi
/** The extended API of sym trees that's supported in macro context universes
+ * @group API
*/
trait TypeTreeContextApi extends TypeTreeApi { this: TypeTree =>
+ /** Sets the `original` field of the type tree. */
def setOriginal(tree: Tree): this.type
}
+ /** @inheritdoc */
override type Ident >: Null <: RefTree with IdentContextApi
/** The extended API of idents that's supported in macro context universes
+ * @group API
*/
trait IdentContextApi extends IdentApi { this: Ident =>
+ /** Was this ident created from a backquoted identifier? */
def isBackquoted: Boolean
}
/** Mark a variable as captured; i.e. force boxing in a *Ref type.
+ * @group Macros
*/
def captureVariable(vble: Symbol): Unit
/** Mark given identifier as a reference to a captured variable itself
* suppressing dereferencing with the `elem` field.
+ * @group Macros
*/
def referenceCapturedVariable(vble: Symbol): Tree
/** Convert type of a captured variable to *Ref type.
+ * @group Macros
*/
def capturedVariableType(vble: Symbol): Type
+ /** The type of compilation runs.
+ * @template
+ * @group Macros
+ */
type Run <: RunContextApi
/** Compilation run uniquely identifies current invocation of the compiler
* (e.g. can be used to implement per-run caches for macros) and provides access to units of work
* of the invocation (currently processed unit of work and the list of all units).
+ * @group API
*/
trait RunContextApi {
/** Currently processed unit of work (a real or a virtual file). */
@@ -137,10 +210,15 @@ abstract class Universe extends scala.reflect.api.Universe {
def units: Iterator[CompilationUnit]
}
+ /** The type of compilation units.
+ * @template
+ * @group Macros
+ */
type CompilationUnit <: CompilationUnitContextApi
/** Compilation unit describes a unit of work of the compilation run.
* It provides such information as file name, textual representation of the unit and the underlying AST.
+ * @group API
*/
trait CompilationUnitContextApi {
/** Source file corresponding to this compilation unit.
@@ -148,7 +226,7 @@ abstract class Universe extends scala.reflect.api.Universe {
* Exposes information about the file as a part of a real or virtual file system
* along with the contents of that file.
*
- * The return type is [[scala.reflect.io.AbstractFile]], which belongs to an experimental part of Scala reflection.
+ * The return type is `scala.reflect.io.AbstractFile`, which belongs to an experimental part of Scala reflection.
* It should not be used unless you know what you are doing. In subsequent releases, this API will be refined
* and exposed as a part of scala.reflect.api.
*/
diff --git a/src/reflect/scala/reflect/macros/package.scala b/src/reflect/scala/reflect/macros/package.scala
index 6a69872367..3a2f04bcf2 100644
--- a/src/reflect/scala/reflect/macros/package.scala
+++ b/src/reflect/scala/reflect/macros/package.scala
@@ -1,4 +1,12 @@
package scala.reflect
+/** The base package for Scala macros.
+ *
+ * Macros are functions that are called by the compiler during compilation.
+ * Within these functions the programmer has access to compiler APIs exposed in [[scala.reflect.macros.Context]].
+ * For example, it is possible to generate, analyze and typecheck code.
+ *
+ * See the [[http://docs.scala-lang.org/overviews/macros.html Macros Guide]] on how to get started with Scala macros.
+ */
package object macros {
} \ No newline at end of file
diff --git a/src/reflect/scala/reflect/runtime/JavaUniverse.scala b/src/reflect/scala/reflect/runtime/JavaUniverse.scala
index 1d875b10f1..e18435d5b0 100644
--- a/src/reflect/scala/reflect/runtime/JavaUniverse.scala
+++ b/src/reflect/scala/reflect/runtime/JavaUniverse.scala
@@ -3,8 +3,11 @@ package runtime
import internal.{SomePhase, NoPhase, Phase, TreeGen}
-/** The universe for standard runtime reflection from Java.
- * This type implements all abstract term members in internal.SymbolTable.
+/** An implementation of [[scala.reflect.api.Universe]] for runtime reflection using JVM classloaders.
+ *
+ * Should not be instantiated directly, use [[scala.reflect.runtime.universe]] instead.
+ *
+ * @contentDiagram hideNodes "*Api" "*Extractor"
*/
class JavaUniverse extends internal.SymbolTable with ReflectSetup with runtime.SymbolTable { self =>
diff --git a/src/reflect/scala/reflect/runtime/package.scala b/src/reflect/scala/reflect/runtime/package.scala
index 278629adb6..b97913daf0 100644
--- a/src/reflect/scala/reflect/runtime/package.scala
+++ b/src/reflect/scala/reflect/runtime/package.scala
@@ -1,10 +1,23 @@
package scala.reflect
+/** Entry points into runtime reflection.
+ * See [[scala.reflect.api.package the overview page]] for details on how to use them.
+ */
package object runtime {
- // type is api.JavaUniverse because we only want to expose the `scala.reflect.api.*` subset of reflection
+ /** The entry point into Scala runtime reflection.
+ *
+ * To use Scala runtime reflection, simply use or import `scala.reflect.runtime.universe._`
+ *
+ * See [[scala.reflect.api.Universe]] or the
+ * [[http://docs.scala-lang.org/overviews/reflection/environment-universes-mirrors.html Reflection Guide: Universes]]
+ * for more details.
+ */
lazy val universe: api.JavaUniverse = new runtime.JavaUniverse
+ /** The runtime reflection mirror that corresponds to the current lexical context.
+ * It's typically equivalent to `universe.runtimeMirror(getClass.getClassLoader)` invoked at the call site.
+ */
// implementation hardwired to the `currentMirror` method below
// using the mechanism implemented in `scala.tools.reflect.FastTrack`
def currentMirror: universe.Mirror = ??? // macro