Skip to content

Commit bbd2e43

Browse files
committed
improved reflection documentation
1 parent 61480eb commit bbd2e43

22 files changed

+591
-181
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 types are
13+
* replaced by the concrete types if ClassTags are available for them.
14+
*
15+
* Besides accessing the erasure, a ClassTag knows how 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

+62-1
Original file line numberDiff line numberDiff line change
@@ -3,42 +3,103 @@ 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.Annotation]] or [[scala.annotation.StaticAnnotation]]
14+
* but not [[scala.annotation.ClassfileAnnotation]] 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, args, javaArgs)`.
28+
* Here, `atp` is the annotation type, `args` the arguments, and `javaArgs` the annotation's key-value
29+
* pairs.
30+
*
31+
* Annotations are written to the classfile as Java annotations if `atp` conforms to
32+
* `ClassfileAnnotation`. Annotations are pickled, i.e., written to scala symtab attribute in the classfile,
33+
* if `atp` inherits from `StaticAnnotation` but not `ClassfileAnnotation`.
34+
*
35+
* For Scala annotations, arguments are stored in `args` and `javaArgs` is empty. Arguments in
36+
* `args` are represented as typed trees. Note that these trees are not transformed by any phases
37+
* following the type-checker. For Java annotations, `args` is empty and arguments are stored in
38+
* `javaArgs`.
39+
*/
1240
abstract class AnnotationExtractor {
1341
def apply(tpe: Type, scalaArgs: List[Tree], javaArgs: ListMap[Name, JavaArgument]): Annotation
1442
def unapply(ann: Annotation): Option[(Type, List[Tree], ListMap[Name, JavaArgument])]
1543
}
1644

45+
/** A Java annotation argument */
1746
type JavaArgument >: Null <: AnyRef
1847
implicit val JavaArgumentTag: ClassTag[JavaArgument]
1948

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

60+
/** An extractor class to create and pattern match with syntax `LiteralArgument(value)`
61+
* where `value` is the constant argument.
62+
*/
2463
abstract class LiteralArgumentExtractor {
2564
def apply(value: Constant): LiteralArgument
2665
def unapply(arg: LiteralArgument): Option[Constant]
2766
}
2867

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

80+
/** An extractor class to create and pattern match with syntax `ArrayArgument(args)`
81+
* where `args` is the argument array.
82+
*/
3383
abstract class ArrayArgumentExtractor {
3484
def apply(args: Array[JavaArgument]): ArrayArgument
3585
def unapply(arg: ArrayArgument): Option[Array[JavaArgument]]
3686
}
3787

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

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

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

+10-7
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,38 @@
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 generalisation of Position. Typically it stores a Position of a tree, but this can be extended to
5+
* encompass arbitrary payloads.
66
*
7-
* Attachments have to carry positions, because we don't want to introduce even a single additional field in Tree
7+
* Attachments always carry positions because we don't want to introduce an additional field for attachments in `Tree`
88
* imposing an unnecessary memory tax because of something that will not be used in most cases.
99
*/
1010
abstract class Attachments { self =>
1111

12+
/** The position type of this attachment */
1213
type Pos >: Null
1314

14-
/** Gets the underlying position */
15+
/** The underlying position */
1516
def pos: Pos
1617

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

20-
/** Gets the underlying payload */
21+
/** The underlying payload. */
2122
def all: Set[Any] = Set.empty
2223

2324
private def matchesTag[T: ClassTag](datum: Any) =
2425
classTag[T].runtimeClass == datum.getClass
2526

27+
/** An underlying payload of the given class type `T`. */
2628
def get[T: ClassTag]: Option[T] =
2729
(all filter matchesTag[T]).headOption.asInstanceOf[Option[T]]
2830

29-
/** Creates a copy of this attachment with its payload updated */
31+
/** Creates a copy of this attachment with a new payload added */
3032
def update[T: ClassTag](attachment: T): Attachments { type Pos = self.Pos } =
3133
new NonemptyAttachments(this.pos, remove[T].all + attachment)
3234

35+
/** Creates a copy of this attachment with all payloads of the given class type `T` removed. */
3336
def remove[T: ClassTag]: Attachments { type Pos = self.Pos } = {
3437
val newAll = all filterNot matchesTag[T]
3538
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

+45-1
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,54 @@ 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 universe given its corresponding mirror.
16+
*/
1417
def in[U <: Universe with Singleton](otherMirror: MirrorOf[U]): U # Expr[T]
1518

19+
/**
20+
* The Scala syntax tree representing the wrapped expression.
21+
*/
1622
def tree: Tree
23+
24+
/**
25+
* Representation of the type of the wrapped expression tree as found via type tags.
26+
*/
1727
def staticType: Type
28+
/**
29+
* Representation of the type of the wrapped expression tree as found in the tree.
30+
*/
1831
def actualType: Type
1932

33+
/**
34+
* A dummy method to mark expression splicing in reification.
35+
* It should only be used within a `reify` call, which eliminates the `splice` call and embeds
36+
* the wrapped tree into the reified surrounding expression.
37+
* If used alone `splice` throws an exception when called at runtime.
38+
*
39+
* If you want to use an Expr in reification of some Scala code, you need to splice it in.
40+
* For an expr of type `Expr[T]`, where `T` has a method `foo`, the following code
41+
* {{{
42+
* reify{ expr.splice.foo }
43+
* }}}
44+
* uses splice to turn an expr of type Expr[T] into a value of type T in the context of `reify`.
45+
*
46+
* It is equivalent to
47+
* {{{
48+
* Select( expr.tree, newTermName("foo") )
49+
* }}}
50+
*
51+
* The following example code however does not compile
52+
* {{{
53+
* reify{ expr.foo }
54+
* }}}
55+
* because expr of type Expr[T] does not have a method foo.
56+
*/
2057
def splice: T
58+
// TODO: document this
2159
val value: T
2260

2361
/** case class accessories */
@@ -27,6 +65,12 @@ trait Exprs { self: Universe =>
2765
override def toString = "Expr["+staticType+"]("+tree+")"
2866
}
2967

68+
/**
69+
* Constructor/Extractor for Expr.
70+
*
71+
* Can be useful, when having a tree and wanting to splice it in reify call,
72+
* in which case the tree first needs to be wrapped in an expr.
73+
*/
3074
object Expr {
3175
def apply[T: WeakTypeTag](mirror: MirrorOf[self.type], treec: TreeCreator): Expr[T] = new ExprImpl[T](mirror.asInstanceOf[Mirror], treec)
3276
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 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
+13-2
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,23 @@
11
package scala.reflect
22
package base
33

4+
/**
5+
* Defines a type hierarchy for mirrors.
6+
*
7+
* Every universe has one or more mirrors. A mirror defines a hierarchy of symbols starting with the root package `_root_`
8+
* and provides methods to locate and define classes and singleton objects in that hierarchy.
9+
*
10+
* On the JVM, there is a one to one correspondance between class loaders and mirrors.
11+
*/
412
trait Mirrors {
513
self: Universe =>
614

7-
/** .. */
15+
/** The base type of all mirrors of this universe */
816
type Mirror >: Null <: MirrorOf[self.type]
917

10-
/** .. */
18+
/** The roor mirror of this universe. This mirror contains standard Scala classes and types such as `Any`, `AnyRef`, `AnyVal`,
19+
* `Nothing`, `Null`, and all classes loaded from scala-library. The root package of this mirror contains the root
20+
* packages of all other mirrors of this universe as members.
21+
*/
1122
val rootMirror: Mirror
1223
}

0 commit comments

Comments
 (0)