Skip to content

Commit eb49e81

Browse files
committed
Merge pull request scala#1335 from cvogt/topic/reflection-scaladoc
improved reflection documentation
2 parents 2222f29 + ecbb25a commit eb49e81

24 files changed

+681
-186
lines changed

src/library/scala/reflect/ClassTag.scala

+13-10
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,17 @@ import java.lang.{ Class => jClass }
55
import scala.language.{implicitConversions, existentials}
66
import scala.runtime.ScalaRunTime.{ arrayClass, arrayElementClass }
77

8-
/** A `ClassTag[T]` wraps a runtime class, which can be accessed via the `runtimeClass` method.
8+
/** A `ClassTag[T]` wraps a runtime class (the erasure) and can create array instances.
99
*
10-
* This is useful in itself, but also enables very important use case.
11-
* Having this knowledge ClassTag can instantiate `Arrays`
12-
* in those cases where the element type is unknown at compile time.
10+
* If an implicit value of type ClassTag[T] is requested, the compiler will create one.
11+
* The runtime class (i.e. the erasure, a java.lang.Class on the JVM) of T can be accessed
12+
* via the `runtimeClass` field. References to type parameters or abstract type members are
13+
* replaced by the concrete types if ClassTags are available for them.
14+
*
15+
* Besides accessing the erasure, a ClassTag knows how to instantiate single- and multi-
16+
* dimensional `Arrays` where the element type is unknown at compile time.
1317
*
14-
* If an implicit value of type u.ClassTag[T] is required, the compiler will make one up on demand.
15-
* The implicitly created value contains in its `runtimeClass` field the runtime class that is the result of erasing type T.
16-
* In that value, any occurrences of type parameters or abstract types U which come themselves with a ClassTag
17-
* are represented by the type referenced by that tag.
18-
* If the type T contains unresolved references to type parameters or abstract types, a static error results.
18+
* [[scala.reflect.ClassTag]] corresponds to a previous concept of [[scala.reflect.ClassManifest]].
1919
*
2020
* @see [[scala.reflect.base.TypeTags]]
2121
*/
@@ -76,7 +76,7 @@ trait ClassTag[T] extends ClassManifestDeprecatedApis[T] with Equals with Serial
7676
if (conforms) Some(x.asInstanceOf[T]) else None
7777
}
7878

79-
/** case class accessories */
79+
// case class accessories
8080
override def canEqual(x: Any) = x.isInstanceOf[ClassTag[_]]
8181
override def equals(x: Any) = x.isInstanceOf[ClassTag[_]] && this.runtimeClass == x.asInstanceOf[ClassTag[_]].runtimeClass
8282
override def hashCode = scala.runtime.ScalaRunTime.hash(runtimeClass)
@@ -88,6 +88,9 @@ trait ClassTag[T] extends ClassManifestDeprecatedApis[T] with Equals with Serial
8888
}
8989
}
9090

91+
/**
92+
* Class tags corresponding to primitive types and constructor/extractor for ClassTags.
93+
*/
9194
object ClassTag {
9295
private val ObjectTYPE = classOf[java.lang.Object]
9396
private val NothingTYPE = classOf[scala.runtime.Nothing$]

src/library/scala/reflect/base/Annotations.scala

+61-1
Original file line numberDiff line numberDiff line change
@@ -3,42 +3,102 @@ package base
33

44
import scala.collection.immutable.ListMap
55

6+
/**
7+
* Defines the type hierarchy for annotations.
8+
*/
69
trait Annotations { self: Universe =>
710

11+
/** Typed information about an annotation. It can be attached to either a symbol or an annotated type.
12+
*
13+
* Annotations are either ''Scala annotations'', which conform to [[scala.annotation.StaticAnnotation]]
14+
* or ''Java annotations'', which conform to [[scala.annotation.ClassfileAnnotation]].
15+
* Trait `ClassfileAnnotation` is automatically added to every Java annotation by the scalac classfile parser.
16+
*/
817
type Annotation >: Null <: AnyRef
18+
19+
/** A tag that preserves the identity of the `Annotation` abstract type from erasure.
20+
* Can be used for pattern matching, instance tests, serialization and likes.
21+
*/
922
implicit val AnnotationTag: ClassTag[Annotation]
10-
val Annotation: AnnotationExtractor
1123

24+
/** The constructor/deconstructor for `Annotation` instances. */
25+
val Annotation: AnnotationExtractor
26+
27+
/** An extractor class to create and pattern match with syntax `Annotation(atp, scalaArgs, javaArgs)`.
28+
* Here, `atp` is the annotation type, `scalaArgs` the arguments, and `javaArgs` the annotation's key-value
29+
* pairs.
30+
*
31+
* Annotations are pickled, i.e. written to scala symtab attribute in the classfile.
32+
* Annotations are written to the classfile as Java annotations if `atp` conforms to `ClassfileAnnotation`.
33+
*
34+
* For Scala annotations, arguments are stored in `scalaArgs` and `javaArgs` is empty. Arguments in
35+
* `scalaArgs` are represented as typed trees. Note that these trees are not transformed by any phases
36+
* following the type-checker. For Java annotations, `scalaArgs` is empty and arguments are stored in
37+
* `javaArgs`.
38+
*/
1239
abstract class AnnotationExtractor {
1340
def apply(tpe: Type, scalaArgs: List[Tree], javaArgs: ListMap[Name, JavaArgument]): Annotation
1441
def unapply(ann: Annotation): Option[(Type, List[Tree], ListMap[Name, JavaArgument])]
1542
}
1643

44+
/** A Java annotation argument */
1745
type JavaArgument >: Null <: AnyRef
1846
implicit val JavaArgumentTag: ClassTag[JavaArgument]
1947

48+
/** A literal argument to a Java annotation as `"Use X instead"` in `@Deprecated("Use X instead")`*/
2049
type LiteralArgument >: Null <: AnyRef with JavaArgument
50+
51+
/** A tag that preserves the identity of the `LiteralArgument` abstract type from erasure.
52+
* Can be used for pattern matching, instance tests, serialization and likes.
53+
*/
2154
implicit val LiteralArgumentTag: ClassTag[LiteralArgument]
55+
56+
/** The constructor/deconstructor for `LiteralArgument` instances. */
2257
val LiteralArgument: LiteralArgumentExtractor
2358

59+
/** An extractor class to create and pattern match with syntax `LiteralArgument(value)`
60+
* where `value` is the constant argument.
61+
*/
2462
abstract class LiteralArgumentExtractor {
2563
def apply(value: Constant): LiteralArgument
2664
def unapply(arg: LiteralArgument): Option[Constant]
2765
}
2866

67+
/** An array argument to a Java annotation as in `@Target(value={TYPE,FIELD,METHOD,PARAMETER})`
68+
*/
2969
type ArrayArgument >: Null <: AnyRef with JavaArgument
70+
71+
/** A tag that preserves the identity of the `ArrayArgument` abstract type from erasure.
72+
* Can be used for pattern matching, instance tests, serialization and likes.
73+
*/
3074
implicit val ArrayArgumentTag: ClassTag[ArrayArgument]
75+
76+
/** The constructor/deconstructor for `ArrayArgument` instances. */
3177
val ArrayArgument: ArrayArgumentExtractor
3278

79+
/** An extractor class to create and pattern match with syntax `ArrayArgument(args)`
80+
* where `args` is the argument array.
81+
*/
3382
abstract class ArrayArgumentExtractor {
3483
def apply(args: Array[JavaArgument]): ArrayArgument
3584
def unapply(arg: ArrayArgument): Option[Array[JavaArgument]]
3685
}
3786

87+
/** A nested annotation argument to a Java annotation as `@Nested` in `@Outer(@Nested)`.
88+
*/
3889
type NestedArgument >: Null <: AnyRef with JavaArgument
90+
91+
/** A tag that preserves the identity of the `NestedArgument` abstract type from erasure.
92+
* Can be used for pattern matching, instance tests, serialization and likes.
93+
*/
3994
implicit val NestedArgumentTag: ClassTag[NestedArgument]
95+
96+
/** The constructor/deconstructor for `NestedArgument` instances. */
4097
val NestedArgument: NestedArgumentExtractor
4198

99+
/** An extractor class to create and pattern match with syntax `NestedArgument(annotation)`
100+
* where `annotation` is the nested annotation.
101+
*/
42102
abstract class NestedArgumentExtractor {
43103
def apply(annotation: Annotation): NestedArgument
44104
def unapply(arg: NestedArgument): Option[Annotation]

src/library/scala/reflect/base/Attachments.scala

+14-7
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,42 @@
11
package scala.reflect
22
package base
33

4-
/** Attachments is a generalisation of Position.
5-
* Typically it stores a Position of a tree, but this can be extended to encompass arbitrary payloads.
4+
/** Attachments is a generalization of Position. Typically it stores a Position of a tree, but this can be extended to
5+
* encompass arbitrary payloads. Payloads are stored in type-indexed slots, which can be read with `get[T]` and written
6+
* with `update[T]` and `remove[T]`.
67
*
7-
* Attachments have to carry positions, because we don't want to introduce even a single additional field in Tree
8+
* Attachments always carry positions because we don't want to introduce an additional field for attachments in `Tree`
89
* imposing an unnecessary memory tax because of something that will not be used in most cases.
910
*/
1011
abstract class Attachments { self =>
1112

13+
/** The position type of this attachment */
1214
type Pos >: Null
1315

14-
/** Gets the underlying position */
16+
/** The underlying position */
1517
def pos: Pos
1618

17-
/** Creates a copy of this attachment with its position updated */
19+
/** Creates a copy of this attachment with the position replaced by `newPos` */
1820
def withPos(newPos: Pos): Attachments { type Pos = self.Pos }
1921

20-
/** Gets the underlying payload */
22+
/** The underlying payload with the guarantee that no two elements have the same type. */
2123
def all: Set[Any] = Set.empty
2224

2325
private def matchesTag[T: ClassTag](datum: Any) =
2426
classTag[T].runtimeClass == datum.getClass
2527

28+
/** An underlying payload of the given class type `T`. */
2629
def get[T: ClassTag]: Option[T] =
2730
(all filter matchesTag[T]).headOption.asInstanceOf[Option[T]]
2831

29-
/** Creates a copy of this attachment with its payload updated */
32+
/** Creates a copy of this attachment with the payload slot of T added/updated with the provided value.
33+
*
34+
* Replaces an existing payload of the same type, if exists.
35+
*/
3036
def update[T: ClassTag](attachment: T): Attachments { type Pos = self.Pos } =
3137
new NonemptyAttachments(this.pos, remove[T].all + attachment)
3238

39+
/** Creates a copy of this attachment with the payload of the given class type `T` removed. */
3340
def remove[T: ClassTag]: Attachments { type Pos = self.Pos } = {
3441
val newAll = all filterNot matchesTag[T]
3542
if (newAll.isEmpty) pos.asInstanceOf[Attachments { type Pos = self.Pos }]

src/library/scala/reflect/base/Base.scala

+3
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@ import scala.ref.WeakReference
77
import scala.collection.mutable
88
import scala.collection.immutable.ListMap
99

10+
/**
11+
* This is an internal implementation class.
12+
*/
1013
class Base extends Universe { self =>
1114

1215
private var nextId = 0

src/library/scala/reflect/base/BuildUtils.scala

+3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
package scala.reflect
22
package base
33

4+
/**
5+
* This is an internal implementation class.
6+
*/
47
trait BuildUtils { self: Universe =>
58

69
val build: BuildBase

src/library/scala/reflect/base/Constants.scala

+16
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,29 @@
66
package scala.reflect
77
package base
88

9+
/**
10+
* Defines the type hierachy for compile-time constants.
11+
*
12+
* @see [[scala.reflect]] for a description on how the class hierarchy is encoded here.
13+
*/
914
trait Constants {
1015
self: Universe =>
1116

17+
/** The type of compile-time constants.
18+
*/
1219
type Constant >: Null <: AnyRef
20+
21+
/** A tag that preserves the identity of the `Constant` abstract type from erasure.
22+
* Can be used for pattern matching, instance tests, serialization and likes.
23+
*/
1324
implicit val ConstantTag: ClassTag[Constant]
25+
26+
/** The constructor/deconstructor for `Constant` instances. */
1427
val Constant: ConstantExtractor
1528

29+
/** An extractor class to create and pattern match with syntax `Constant(value)`
30+
* where `value` is the Scala value of the constant.
31+
*/
1632
abstract class ConstantExtractor {
1733
def apply(value: Any): Constant
1834
def unapply(arg: Constant): Option[Any]

src/library/scala/reflect/base/Exprs.scala

+62-1
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,71 @@ package base
88

99
trait Exprs { self: Universe =>
1010

11-
/** An expression tree tagged with its type */
11+
/** Expr wraps an expression tree and tags it with its type. */
1212
trait Expr[+T] extends Equals with Serializable {
1313
val mirror: Mirror
14+
/**
15+
* Migrates the expression into another mirror, jumping into a different universe if necessary.
16+
*
17+
* This means that all symbolic references to classes/objects/packages in the expression
18+
* will be re-resolved within the new mirror (typically using that mirror's classloader).
19+
*/
1420
def in[U <: Universe with Singleton](otherMirror: MirrorOf[U]): U # Expr[T]
1521

22+
/**
23+
* The Scala syntax tree representing the wrapped expression.
24+
*/
1625
def tree: Tree
26+
27+
/**
28+
* Representation of the type of the wrapped expression tree as found via type tags.
29+
*/
1730
def staticType: Type
31+
/**
32+
* Representation of the type of the wrapped expression tree as found in the tree.
33+
*/
1834
def actualType: Type
1935

36+
/**
37+
* A dummy method to mark expression splicing in reification.
38+
*
39+
* It should only be used within a `reify` call, which eliminates the `splice` call and embeds
40+
* the wrapped tree into the reified surrounding expression.
41+
* If used alone `splice` throws an exception when called at runtime.
42+
*
43+
* If you want to use an Expr in reification of some Scala code, you need to splice it in.
44+
* For an expr of type `Expr[T]`, where `T` has a method `foo`, the following code
45+
* {{{
46+
* reify{ expr.splice.foo }
47+
* }}}
48+
* uses splice to turn an expr of type Expr[T] into a value of type T in the context of `reify`.
49+
*
50+
* It is equivalent to
51+
* {{{
52+
* Select( expr.tree, newTermName("foo") )
53+
* }}}
54+
*
55+
* The following example code however does not compile
56+
* {{{
57+
* reify{ expr.foo }
58+
* }}}
59+
* because expr of type Expr[T] itself does not have a method foo.
60+
*/
2061
def splice: T
62+
/**
63+
* A dummy value to denote cross-stage path-dependent type dependencies.
64+
*
65+
* For example for the following macro definition:
66+
* {{{
67+
* class X { type T }
68+
* object Macros { def foo(x: X): x.T = macro Impls.foo_impl }
69+
* }}}
70+
*
71+
* The corresponding macro implementation should have the following signature (note how the return type denotes path-dependency on x):
72+
* {{{
73+
* object Impls { def foo_impl(c: Context)(x: c.Expr[X]): c.Expr[x.value.T] = ... }
74+
* }}}
75+
*/
2176
val value: T
2277

2378
/** case class accessories */
@@ -27,6 +82,12 @@ trait Exprs { self: Universe =>
2782
override def toString = "Expr["+staticType+"]("+tree+")"
2883
}
2984

85+
/**
86+
* Constructor/Extractor for Expr.
87+
*
88+
* Can be useful, when having a tree and wanting to splice it in reify call,
89+
* in which case the tree first needs to be wrapped in an expr.
90+
*/
3091
object Expr {
3192
def apply[T: WeakTypeTag](mirror: MirrorOf[self.type], treec: TreeCreator): Expr[T] = new ExprImpl[T](mirror.asInstanceOf[Mirror], treec)
3293
def unapply[T](expr: Expr[T]): Option[Tree] = Some(expr.tree)

src/library/scala/reflect/base/FlagSets.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ package base
33

44
trait FlagSets { self: Universe =>
55

6-
/** An abstract type representing sets of flags that apply to definition trees and symbols */
6+
/** An abstract type representing sets of flags (like private, final, etc.) that apply to definition trees and symbols */
77
type FlagSet
88

99
/** A tag that preserves the identity of the `FlagSet` abstract type from erasure.

src/library/scala/reflect/base/MirrorOf.scala

+21-2
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,33 @@
11
package scala.reflect
22
package base
33

4+
/**
5+
* The base interface for all mirrors.
6+
*
7+
* @tparam U the type of the universe this mirror belongs to.
8+
*
9+
* This is defined outside the reflection universe cake pattern implementation
10+
* so that it can be referenced from outside. For example TypeCreator and TreeCreator
11+
* reference MirrorOf and also need to be defined outside the cake as they are
12+
* used by type tags, which can be migrated between different universes and consequently
13+
* cannot be bound to a fixed one.
14+
*
15+
* @see [[Mirrors]]
16+
*/
417
abstract class MirrorOf[U <: base.Universe with Singleton] {
5-
/** .. */
18+
/** The universe this mirror belongs to. */
619
val universe: U
720

8-
/** .. */
21+
/** The class symbol of the `_root_` package */
922
def RootClass: U#ClassSymbol
23+
24+
/** The module symbol of the `_root_` package */
1025
def RootPackage: U#ModuleSymbol
26+
27+
/** The module class symbol of the default (unnamed) package */
1128
def EmptyPackageClass: U#ClassSymbol
29+
30+
/** The module symbol of the default (unnamed) package */
1231
def EmptyPackage: U#ModuleSymbol
1332

1433
/** The symbol corresponding to the globally accessible class with the

0 commit comments

Comments
 (0)