From e95a00992599f59f7c74bcc171bb290f859ab848 Mon Sep 17 00:00:00 2001 From: Heather Miller Date: Thu, 11 Oct 2012 20:31:42 +0200 Subject: Adds lots of new documentation for TypeTags, Mirrors, Universes and more Additionally includes improvements, formatting fixes, and link additions and fixes. --- src/reflect/scala/reflect/api/Annotations.scala | 13 +- src/reflect/scala/reflect/api/Constants.scala | 76 +++++- src/reflect/scala/reflect/api/Exprs.scala | 3 +- src/reflect/scala/reflect/api/FlagSets.scala | 59 +++-- src/reflect/scala/reflect/api/Importers.scala | 34 +-- src/reflect/scala/reflect/api/JavaMirrors.scala | 22 +- src/reflect/scala/reflect/api/Mirror.scala | 13 +- src/reflect/scala/reflect/api/Mirrors.scala | 201 +++++++++++++++- src/reflect/scala/reflect/api/Names.scala | 4 +- src/reflect/scala/reflect/api/Position.scala | 24 ++ src/reflect/scala/reflect/api/Printers.scala | 78 ++++--- .../scala/reflect/api/StandardDefinitions.scala | 7 +- src/reflect/scala/reflect/api/StandardNames.scala | 3 +- src/reflect/scala/reflect/api/TreeCreator.scala | 2 +- src/reflect/scala/reflect/api/TypeCreator.scala | 6 +- src/reflect/scala/reflect/api/TypeTags.scala | 256 +++++++++++---------- src/reflect/scala/reflect/api/Universe.scala | 131 +++-------- src/reflect/scala/reflect/api/package.scala | 19 +- src/reflect/scala/reflect/runtime/package.scala | 12 +- 19 files changed, 621 insertions(+), 342 deletions(-) (limited to 'src/reflect') diff --git a/src/reflect/scala/reflect/api/Annotations.scala b/src/reflect/scala/reflect/api/Annotations.scala index 1e658228f3..fb353a5520 100644 --- a/src/reflect/scala/reflect/api/Annotations.scala +++ b/src/reflect/scala/reflect/api/Annotations.scala @@ -6,11 +6,16 @@ import scala.collection.immutable.ListMap /** This trait provides annotation support for the reflection API. * * The API distinguishes between two kinds of annotations: - * 1. ''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. - * 1. ''Scala annotations'': annotations on definitions or types produced by the Scala compiler. * - * 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 + * + * + * 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 diff --git a/src/reflect/scala/reflect/api/Constants.scala b/src/reflect/scala/reflect/api/Constants.scala index 9e0573f0dc..a92fc5cbb3 100644 --- a/src/reflect/scala/reflect/api/Constants.scala +++ b/src/reflect/scala/reflect/api/Constants.scala @@ -7,9 +7,79 @@ package scala.reflect package api /** - * This trait is the [[scala.reflect.api.Universe reflection API]] component that mirrors constant irreducible expressions - * such as `true`, `0` and `classOf[List]`. Constant values appear in the program abstract syntax tree and in annotation parameters - * wrapped in [[Constant `Constant`]] case classes. + * According to the section 6.24 "Constant Expressions" of the Scala language specification, + * certain expressions (dubbed ''constant expressions'') can be evaluated by the Scala compiler at compile-time. + * + * [[scala.reflect.api.Constants#Constant]] instances represent certain kinds of these expressions + * (with values stored in the `value` field and its strongly-typed views named `booleanValue`, `intValue` etc.), namely: + * 1. Literals of primitive value classes (bytes, shorts, ints, longs, floats, doubles, chars, booleans and voids). + * 1. String literals. + * 1. References to classes (typically constructed with [[scala.Predef#classOf]]). + * 1. References to enumeration values. + * + * Such constants are used to represent literals in abstract syntax trees (the [[scala.reflect.api.Trees#Literal]] node) + * and literal arguments for Java class file annotations (the [[scala.reflect.api.Annotations#LiteralArgument]] class). + * + * === Example === + * + * The `value` field deserves some explanation. Primitive and string values are represented as themselves, whereas + * references to classes and enums are a bit roundabout. + * + * Class references are represented as instances of [[scala.reflect.api.Types#Type]] + * (because when the Scala compiler processes a class reference, the underlying runtime class might not yet have been compiled). + * To convert such a reference to a runtime class, one should use the `runtimeClass` method of a mirror such as [[scala.reflect.api.Mirrors#RuntimeMirror]] + * (the simplest way to get such a mirror is using [[scala.reflect.runtime.package#currentMirror]]). + * + * Enumeration value references are represented as instances of [[scala.reflect.api.Symbols#Symbol]], which on JVM point to methods + * that return underlying enum values. To inspect an underlying enumeration or to get runtime value of a reference to an enum, + * one should use a [[scala.reflect.api.Mirrors#RuntimeMirror]] (the simplest way to get such a mirror is again [[scala.reflect.runtime.package#currentMirror]]). + + * {{{ + * enum JavaSimpleEnumeration { FOO, BAR } + * + * import java.lang.annotation.*; + * @Retention(RetentionPolicy.RUNTIME) + * @Target({ElementType.TYPE}) + * public @interface JavaSimpleAnnotation { + * Class classRef(); + * JavaSimpleEnumeration enumRef(); + * } + * + * @JavaSimpleAnnotation( + * classRef = JavaAnnottee.class, + * enumRef = JavaSimpleEnumeration.BAR + * ) + * public class JavaAnnottee {} + * }}} + * {{{ + * import scala.reflect.runtime.universe._ + * import scala.reflect.runtime.{currentMirror => cm} + * + * object Test extends App { + * val jann = typeOf[JavaAnnottee].typeSymbol.annotations(0).javaArgs + * def jarg(name: String) = jann(newTermName(name)).asInstanceOf[LiteralArgument].value + * + * val classRef = jarg("classRef").typeValue + * println(showRaw(classRef)) // TypeRef(ThisType(), 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" */ diff --git a/src/reflect/scala/reflect/api/Exprs.scala b/src/reflect/scala/reflect/api/Exprs.scala index 788fc889a8..45bfddb55d 100644 --- a/src/reflect/scala/reflect/api/Exprs.scala +++ b/src/reflect/scala/reflect/api/Exprs.scala @@ -8,8 +8,7 @@ package api import scala.reflect.runtime.{universe => ru} -/** A slice of [[scala.reflect.api.Universe the Scala reflection cake]] that defines strongly-typed tree wrappers and operations on them. - * See [[scala.reflect.api.Universe]] for a description of how the reflection API is encoded with the cake pattern. +/** 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]]). * diff --git a/src/reflect/scala/reflect/api/FlagSets.scala b/src/reflect/scala/reflect/api/FlagSets.scala index 701442b632..a7d1ca05a6 100644 --- a/src/reflect/scala/reflect/api/FlagSets.scala +++ b/src/reflect/scala/reflect/api/FlagSets.scala @@ -3,32 +3,51 @@ package api import scala.language.implicitConversions -/** A slice of [[scala.reflect.api.Universe the Scala reflection cake]] that defines flag sets and operations on them. - * See [[scala.reflect.api.Universe]] for a description of how the reflection API is encoded with the cake pattern. +/** + * The trait that defines flag sets and operations on them. * - * Flags 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) and - * [[scala.reflect.api.Trees#TypeDef]] (type aliases, abstract type members and type parameters). + * `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: * - * For example, to create a class named `C` one would write `ClassDef(Modifiers(NoFlags), newTypeName("C"), Nil, ...)`. - * Here the flag set is empty, representing a vanilla class definition. To make `C` private, one would write - * `ClassDef(Modifiers(PRIVATE), newTypeName("C"), Nil, ...)`. Flags can also be combined with the vertical bar operator (`|`). - * For example, a private final class is written as followed: `ClassDef(Modifiers(PRIVATE | FINAL), newTypeName("C"), Nil, ...)`. + * - '''[[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. * - * The list of all available flags is defined in [[scala.reflect.api.FlagSets#FlagValues]], available via the [[scala.reflect.api.FlagSets#Flag]] - * (typically one writes a blanket import for that, e.g. `import scala.reflect.runtime.universe.Flag._`). + * 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. * - * Definition trees are compiled down to symbols, so flags on modifiers of such 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 flavors of symbols. + * To make `C` private, one would write something like: + * {{{ + * ClassDef(Modifiers(PRIVATE), newTypeName("C"), Nil, ...) + * }}} * - * === Known issues === + * 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]] * - * This API is considered to be a candidate for redesign. It is quite probable that in future releases of the reflection API - * flag sets will be replaced with something else. */ trait FlagSets { self: Universe => diff --git a/src/reflect/scala/reflect/api/Importers.scala b/src/reflect/scala/reflect/api/Importers.scala index fde8794348..4286b2b45c 100644 --- a/src/reflect/scala/reflect/api/Importers.scala +++ b/src/reflect/scala/reflect/api/Importers.scala @@ -3,33 +3,23 @@ package api /** This trait provides support for importers, a facility to migrate reflection artifacts between universes. * - * Reflection artifacts, such as symbols and types, are contained in universes. 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 + * 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 universes, which is reflected by the fact that types of artifacts - * from different universes are not compatible. By using importers, 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. + * 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 signaturers into the target universe. + * and will import the corresponding type signatures into the target `Universe`. * - * Since importers match symbol tables of the source and the target universes using plain string names, + * 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. - * - * === Known issues === - * - * Importers didn't undergo as much testing as most of the reflection API did, - * so they might be flaky from time to time. Please report issues if you encounter them. - * - * Importers are currently not mirror-aware, they always use `rootMirror` - * of the target universe to resolve symbols. This might cause troubles in cases when the target universe - * need a non-standard way of symbol resolution (e.g. a classloader that's different from the default one). - * We have created [[https://issues.scala-lang.org/browse/SI-6241 https://issues.scala-lang.org/browse/SI-6241]], - * an issue in the issue tracker, to track the implementation of this feature. + * `foo.bar.Baz` in the source `Universe` means the same that `foo.bar.Baz` does in the target `Universe`. * * === Example === * diff --git a/src/reflect/scala/reflect/api/JavaMirrors.scala b/src/reflect/scala/reflect/api/JavaMirrors.scala index 9bc888b884..df099006b5 100644 --- a/src/reflect/scala/reflect/api/JavaMirrors.scala +++ b/src/reflect/scala/reflect/api/JavaMirrors.scala @@ -5,7 +5,12 @@ package api * * 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/settings field values, calling methods, etc). + * 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 => @@ -15,7 +20,7 @@ trait JavaMirrors { self: JavaUniverse => */ type RuntimeClass = java.lang.Class[_] - /** In runtime reflection universes, mirrors are JavaMirrors. + /** In runtime reflection universes, mirrors are `JavaMirrors`. * @group JavaMirrors */ override type Mirror >: Null <: JavaMirror @@ -23,10 +28,12 @@ trait JavaMirrors { self: JavaUniverse => /** 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/settings field values, calling methods, etc). + * 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]] * - * See [[scala.reflect.api.package the overview page]] for details on how to use runtime reflection. * @group JavaMirrors */ trait JavaMirror extends scala.reflect.api.Mirror[self.type] with RuntimeMirror { @@ -35,7 +42,10 @@ trait JavaMirrors { self: JavaUniverse => } /** Creates a runtime reflection mirror from a JVM classloader. - * See [[scala.reflect.api.package the overview page]] for details on how to use runtime reflection. + * + * 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/Mirror.scala b/src/reflect/scala/reflect/api/Mirror.scala index 60ba087933..b1290cc02e 100644 --- a/src/reflect/scala/reflect/api/Mirror.scala +++ b/src/reflect/scala/reflect/api/Mirror.scala @@ -4,16 +4,15 @@ package api /** * The base class for all mirrors. * - * See the [[http://docs.scala-lang.org/overviews/reflection/overview.html Reflection Guide]] for a description of mirrors - * and infomation on getting started with Scala reflection API. - * - * 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. + * See [[scala.reflect.api.Mirrors]] or [[docs.scala-lang.org/overviews/reflection/overview.html Reflection Guide]] + * for a complete overview of `Mirror`s. * * @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. * @group Mirror diff --git a/src/reflect/scala/reflect/api/Mirrors.scala b/src/reflect/scala/reflect/api/Mirrors.scala index 32cfdf07fb..cc1b9762cb 100644 --- a/src/reflect/scala/reflect/api/Mirrors.scala +++ b/src/reflect/scala/reflect/api/Mirrors.scala @@ -1,10 +1,205 @@ package scala.reflect package api -/** This trait provides support for Mirrors in the reflection API. +/** This trait provides support for Mirrors in the Scala Reflection API. * - * See the [[http://docs.scala-lang.org/overviews/reflection/overview.html Reflection Guide]] for a description of mirrors - * and infomation on getting started with Scala reflection API. + * `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. + * + * The two flavors of mirrors: + * + * + * + * === 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()`, 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()`. + * 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()`. + * 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()`. + * 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()`. + * 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()`, + * for ''inner classes'' `val mm2 = im.reflectClass()`. + * 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.(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()`, + * for ''inner objects (modules)'' `val mm2 = im.reflectModule()`. + * 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" */ diff --git a/src/reflect/scala/reflect/api/Names.scala b/src/reflect/scala/reflect/api/Names.scala index 332c24e542..02eb79f8ed 100644 --- a/src/reflect/scala/reflect/api/Names.scala +++ b/src/reflect/scala/reflect/api/Names.scala @@ -5,7 +5,7 @@ package api * * 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. + * same name can co-exist in an object. * * === Examples === * @@ -13,7 +13,7 @@ package api * use `typeOf[List[_]].member(newTermName("map"))`. To search for a type member, use * newTypeName instead. * - * @see [[http://docs.scala-lang.org/overviews/reflection/overview.html]]. + * See the [[docs.scala-lang.org/overviews/reflection/overview.html Reflection Guide]] for more about Scala Reflection. * * @contentDiagram hideNodes "*Api" */ diff --git a/src/reflect/scala/reflect/api/Position.scala b/src/reflect/scala/reflect/api/Position.scala index fb199bbd69..61d643b449 100644 --- a/src/reflect/scala/reflect/api/Position.scala +++ b/src/reflect/scala/reflect/api/Position.scala @@ -16,6 +16,30 @@ import scala.reflect.macros.Attachments * 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, + * 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, + * `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)`. + * 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. + * * @groupname Common Commonly used methods */ trait Position extends Attachments { diff --git a/src/reflect/scala/reflect/api/Printers.scala b/src/reflect/scala/reflect/api/Printers.scala index b7157af153..1e8161aeef 100644 --- a/src/reflect/scala/reflect/api/Printers.scala +++ b/src/reflect/scala/reflect/api/Printers.scala @@ -3,9 +3,12 @@ package api import java.io.{ PrintWriter, StringWriter } -/** A slice of [[scala.reflect.api.Universe the Scala reflection cake]] that defines prettyprinting functionality. +/** Utilities for nicely printing [[scala.reflect.api.Trees]] and [[scala.reflect.api.Types]]. * - * === Examples (trees) === + * === 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._ @@ -14,9 +17,6 @@ import java.io.{ PrintWriter, StringWriter } * scala> def tree = reify{ final class C { def x = 2 } }.tree * tree: reflect.runtime.universe.Tree * - * // show displays prettified representation of reflection artifacts - * // which is typically close to Scala code, but sometimes not quite - * // (e.g. here the constructor is shown in a desugared way) * scala> show(tree) * res0: String = * { @@ -29,21 +29,17 @@ import java.io.{ PrintWriter, StringWriter } * }; * () * } + * }}} + * + * 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. * - * // showRaw displays internal structure of a given reflection object - * // trees and types (type examples are shown below) are case classes - * // so they are shown in a form that's almost copy/pasteable - * // - * // almost copy/pasteable, but not completely - that's because of symbols - * // there's no good way to get a roundtrip-surviving representation of symbols - * // in general case, therefore only symbol names are shown (e.g. take a look at AnyRef) - * // - * // in such a representation, it's impossible to distinguish Idents/Selects - * // that have underlying symbols vs ones that don't have symbols, because in both cases - * // only names will be printed - * // - * // to overcome this limitation, use `printIds` and `printKinds` - optional parameters - * // of the `showRaw` method (an example is shown below) + * 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( @@ -57,15 +53,17 @@ import java.io.{ PrintWriter, StringWriter } * 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} * - * // showRaw can also print types next to the artifacts being inspected - * // provide true for a `printTypes` arguments to achieve this effect * scala> showRaw(cm.mkToolBox().typeCheck(tree), printTypes = true) * res2: String = Block[1](List( * ClassDef[2](Modifiers(FINAL), newTypeName("C"), List(), Template[3]( @@ -89,8 +87,9 @@ import java.io.{ PrintWriter, StringWriter } * [8] ConstantType(Constant(2)) * }}} * - * === Examples (types) === + * === Printing Types === * + * The method `show` * {{{ * scala> import scala.reflect.runtime.universe._ * import scala.reflect.runtime.universe._ @@ -98,10 +97,14 @@ import java.io.{ PrintWriter, StringWriter } * scala> def tpe = typeOf[{ def x: Int; val y: List[Int] }] * tpe: reflect.runtime.universe.Type * - * // show has already been discussed above * 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( @@ -109,18 +112,10 @@ import java.io.{ PrintWriter, StringWriter } * Scope( * newTermName("x"), * newTermName("y"))) + * }}} * - * // when `printIds` and/or `printKinds` arguments are provided for showRaw - * // the prettyprinter reveals underlying symbols and their flavors - * // - * // courtesy of `printKinds` we can see four different symbols: a package class `scala`, - * // a type alias `AnyRef`, a method named `x` and a getter named `y`. - * // - * // thanks to `printIds` we can see unique identifiers of symbols - * // so that it becomes possible to distinguish, say, `scala.collection.immutable.List` - * // from `scala.collection.mutable.List` (this also helps in rare cases - * // when the same reflection entity is represented by multiple symbols, but let's - * // not speak of these horrors here) + * `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())), @@ -128,6 +123,10 @@ import java.io.{ PrintWriter, StringWriter } * 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 => @@ -176,8 +175,9 @@ trait Printers { self: Universe => */ 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 = @@ -188,7 +188,9 @@ trait Printers { self: Universe => */ 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 = diff --git a/src/reflect/scala/reflect/api/StandardDefinitions.scala b/src/reflect/scala/reflect/api/StandardDefinitions.scala index e1eadde3ad..a31a501357 100644 --- a/src/reflect/scala/reflect/api/StandardDefinitions.scala +++ b/src/reflect/scala/reflect/api/StandardDefinitions.scala @@ -5,10 +5,11 @@ package scala.reflect package api -/** A slice of [[scala.reflect.api.Universe the Scala reflection cake]] that defines standard symbols and types. +/** All Scala standard symbols and types. * - * These standard reflection artifacts can be referred to using `definitions` (typically imported with - * a blanket import `import definitions._`) and are listed in [[scala.reflect.api.StandardDefinitions#DefinitionsApi]]. + * 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 => diff --git a/src/reflect/scala/reflect/api/StandardNames.scala b/src/reflect/scala/reflect/api/StandardNames.scala index 203bcdbdc4..fc18c02706 100644 --- a/src/reflect/scala/reflect/api/StandardNames.scala +++ b/src/reflect/scala/reflect/api/StandardNames.scala @@ -10,8 +10,7 @@ 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. -/** This trait is the [[scala.reflect.api.Universe reflection API]] component that defines standard [[Names names used in reflection and macros]]. - * +/** * Standard names are names that are essential to creating trees or to reflecting Scala artifacts. * For example, `CONSTRUCTOR` (aka `` on JVM) is necessary to create and invoke constructors. * diff --git a/src/reflect/scala/reflect/api/TreeCreator.scala b/src/reflect/scala/reflect/api/TreeCreator.scala index c668fe0b4d..cba90b72e6 100644 --- a/src/reflect/scala/reflect/api/TreeCreator.scala +++ b/src/reflect/scala/reflect/api/TreeCreator.scala @@ -3,7 +3,7 @@ package api /** This is an internal implementation class. * - * @see [[http://docs.scala-lang.org/overviews/reflection/architecture.html]]. + * 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/TypeCreator.scala b/src/reflect/scala/reflect/api/TypeCreator.scala index 16585cd23f..9c386f2939 100644 --- a/src/reflect/scala/reflect/api/TypeCreator.scala +++ b/src/reflect/scala/reflect/api/TypeCreator.scala @@ -1,9 +1,9 @@ package scala.reflect package api -/** This is an internal implementation class. - * - * @see [[http://docs.scala-lang.org/overviews/reflection/architecture.html]]. +/** A mirror-aware factory for types. + * + * 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 9d66a9e236..812d5199fc 100644 --- a/src/reflect/scala/reflect/api/TypeTags.scala +++ b/src/reflect/scala/reflect/api/TypeTags.scala @@ -17,130 +17,143 @@ import scala.language.implicitConversions * [Chris++] tag.in(some mirror) or expr.in(some mirror) (does not work for tag and exprs in macros) * Backwards compat item1: [Eugene++] it might be useful, though, to guard against abstractness of the incoming type. */ -/** A slice of [[scala.reflect.api.Universe the Scala reflection cake]] that defines type tags and operations on them. - * See [[scala.reflect.api.Universe]] for a description of how the reflection API is encoded with the cake pattern. - * - * 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]]. - * - * 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]]] - * :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`: + * + *
    + *
  • [[scala.reflect.api.TypeTags#TypeTag]].
    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]`.
  • + * + *
  • [[scala.reflect.ClassTag]].
    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]]
  • + * + *
  • [[scala.reflect.api.TypeTags#WeakTypeTag]].
    A type descriptor for abstract + * types (see description below).
  • + *
+ * + * 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: * {{{ - * 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._ + * 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) * }}} * - * 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. + * === #3 Context bound of a type parameter === * - * 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. + * ...on methods or classes. The above example can be implemented as follows: * - * === Backward compatibility with Manifests === + * {{{ + * 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() * - * Type tags correspond loosely to manifests. + * scala> paramInfo(List(1, 2)) + * type of List(1, 2) has type arguments List(Int) + * }}} + * + * === `WeakTypeTag`s === + * + *`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]`. * - * 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, + * 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") + * } * - * In Scala 2.10 class manifests are deprecated, and manifests are planned to be deprecated in one of the - * subsequent point releases. Therefore it's advisable to migrate manifests to tags. + * scala> def foo[T] = weakParamInfo(List[T]()) + * foo: [T]=> Unit * - * In most cases it is enough to replace `ClassManifest` with `ClassTag` and `Manifest` with `TypeTag`. - * There are however a few caveats: + * scala> foo[Int] + * type of List() has type arguments List(T) + * }}} * - * 1) Tags don't support the notion of `OptManifest`. Tags can reify arbitrary types, so they are always available. + * === TypeTags and Manifests === * - * 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 `.tpe.typeSymbol.isPrimitiveValueClass`. + * `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. * - * 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). + *
    + *
  • '''[[scala.reflect.OptManifest]] is not supported.'''
    This is because `Tag`s + * can reify arbitrary types, so they are always available.
  • * - * 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. + *
  • '''There is no equivalent for [[scala.reflect.AnyValManifest]].'''
    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 + * `.tpe.typeSymbol.isPrimitiveValueClass`.
  • * - * === Known issues === + *
  • '''There are no replacement for factory methods defined in the `Manifest` + * companion objects'''.
    Instead, one could generate corresponding types using the + * reflection APIs provided by Java (for classes) and Scala (for types).
  • * - * Type tags are marked as serializable, but this functionality is not yet implemented. - * An issue tracker entry: [[https://issues.scala-lang.org/browse/SI-5919 https://issues.scala-lang.org/browse/SI-5919]] - * has been created to track the implementation of this feature. + *
  • '''Certain manifest operations(i.e., <:<, >:> and typeArguments) are not + * supported.'''
    Instead, one culd use the reflection APIs provided by Java (for + * classes) and Scala (for types).
  • + *
* - * @see [[scala.reflect.ClassTag]], [[scala.reflect.api.Universe#TypeTag]], [[scala.reflect.api.Universe#WeakTypeTag]] + * 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. + * + * 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 => @@ -148,14 +161,17 @@ 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 @@ -163,7 +179,7 @@ trait TypeTags { self: Universe => @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 @@ -180,16 +196,16 @@ trait TypeTags { self: Universe => */ def tpe: Type - /** TODO how do I doc this? */ + // TODO how do I doc this? override def canEqual(x: Any) = x.isInstanceOf[WeakTypeTag[_]] - /** TODO how do I doc this? */ + // 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? */ + // TODO how do I doc this? override def hashCode = mirror.hashCode * 31 + tpe.hashCode - /** TODO how do I doc this? */ + // TODO how do I doc this? override def toString = "WeakTypeTag[" + tpe + "]" } @@ -249,7 +265,7 @@ 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 not contain any references to * unresolved type parameters or abstract types. * diff --git a/src/reflect/scala/reflect/api/Universe.scala b/src/reflect/scala/reflect/api/Universe.scala index d9be73fde9..7d1f5c9df1 100644 --- a/src/reflect/scala/reflect/api/Universe.scala +++ b/src/reflect/scala/reflect/api/Universe.scala @@ -2,13 +2,18 @@ package scala.reflect package api /** - * The Scala reflection cake. + * `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. * - * See [[scala.reflect.api.package the overview page]] for a description of universes and infomation on getting started with Scala reflection API. - * This page lists the most important layers of the cake, and describes paculiarities of cake APIs. + * [[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. * - * 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: + * `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 @@ -19,58 +24,32 @@ package api * - [[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] + * }}} * - * 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.macros]] 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. - * + * To obtain a `Universe` for use within a Scala macro, use [[scala.reflect.macros.Context#universe]]. For example: * {{{ - * 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) + * 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._ + * ... + * } * }}} * - * is equivalent to - * - * {{{ - * import scala.reflect.runtime.universe._ - * val iftree = reify{ if( condition ) 1 else 2 }.tree - * }}} + * For more information about `Universe`s, see the [[http://docs.scala-lang.org/overviews/reflection/environment-universes-mirrors.html Reflection Guide: Universes]] * - * 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`. - * @groupprio Universe -1 + * @groupprio Universe -1 * * @contentDiagram hideNodes "*Api" */ @@ -93,9 +72,9 @@ 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)) @@ -105,49 +84,7 @@ abstract class Universe extends Symbols * * 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", , 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` diff --git a/src/reflect/scala/reflect/api/package.scala b/src/reflect/scala/reflect/api/package.scala index 449b7d5ce1..bd9c72a839 100644 --- a/src/reflect/scala/reflect/api/package.scala +++ b/src/reflect/scala/reflect/api/package.scala @@ -2,13 +2,22 @@ package scala.reflect import scala.reflect.api.{Universe => ApiUniverse} -/** The Scala reflection API (located at scala-reflect.jar). +/** The Scala Reflection API (located in scala-reflect.jar). * - * Using Scala reflection requires understanding of a couple of basic concepts like [[Symbols Symbols]], [[Types Types]], [[Mirror Mirrors]] and [[Universe Universes]]. - * @see [[http://docs.scala-lang.org/overviews/reflection/overview.html]]. + * 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. * - * In Scala 2.10.0, reflection API and its implementation have 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 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 diff --git a/src/reflect/scala/reflect/runtime/package.scala b/src/reflect/scala/reflect/runtime/package.scala index b3f9ba5817..b97913daf0 100644 --- a/src/reflect/scala/reflect/runtime/package.scala +++ b/src/reflect/scala/reflect/runtime/package.scala @@ -5,14 +5,18 @@ package scala.reflect */ package object runtime { - /** The entry point into runtime reflection. - * See [[scala.reflect.api.package the overview page]] for details on how to use it. + /** 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. - * Is typically equivalent to `universe.runtimeMirror(getClass.getClassLoader)` invoked at the call site. - * See [[scala.reflect.api.package the overview page]] for details on how to use it. + * 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` -- cgit v1.2.3