summaryrefslogtreecommitdiff
path: root/src/reflect/scala/reflect/api/Mirror.scala
blob: 318fdb369aafb05bd4952f4ab9d997df256daac8 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
package scala
package reflect
package api

/**
 * <span class="badge badge-red" style="float: right;">EXPERIMENTAL</span>
 *
 * The base class for all mirrors.
 *
 * 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.
 *  @group ReflectionAPI
 */
// 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
   */
  val universe: U

  /** The class symbol of the `_root_` package
   *  @group Mirror
   */
  def RootClass: U#ClassSymbol

  /** The module symbol of the `_root_` package
   *  @group Mirror
   */
  def RootPackage: U#ModuleSymbol

  /** The module class symbol of the default (unnamed) package
   *  @group Mirror
   */
  def EmptyPackageClass: U#ClassSymbol

  /** The module symbol of the default (unnamed) package
   *  @group Mirror
   */
  def EmptyPackage: U#ModuleSymbol

  /** The symbol corresponding to the globally accessible class with the
   *  given fully qualified name `fullName`.
   *
   *  If the name points to a type alias, it's recursively dealiased and its target is returned.
   *  If you need a symbol that corresponds to the type alias itself, load it directly from the package class:
   *
   *    scala> cm.staticClass("scala.List")
   *    res0: scala.reflect.runtime.universe.ClassSymbol = class List
   *
   *    scala> res0.fullName
   *    res1: String = scala.collection.immutable.List
   *
   *    scala> cm.staticPackage("scala")
   *    res2: scala.reflect.runtime.universe.ModuleSymbol = package scala
   *
   *    scala> res2.moduleClass.info member newTypeName("List")
   *    res3: scala.reflect.runtime.universe.Symbol = type List
   *
   *    scala> res3.fullName
   *    res4: String = scala.List
   *
   *  To be consistent with Scala name resolution rules, in case of ambiguity between
   *  a package and an object, the object is never been considered.
   *
   *  For example for the following code:
   *
   *    package foo {
   *      class B
   *    }
   *
   *    object foo {
   *      class A
   *      class B
   *    }
   *
   *  staticClass("foo.B") will resolve to the symbol corresponding to the class B declared in the package foo, and
   *  staticClass("foo.A") will throw a ScalaReflectionException.
   *
   *  In the example above, to load a symbol that corresponds to the class B declared in the object foo,
   *  use staticModule("foo") to load the module symbol and then navigate info.members of its moduleClass.
   *  @group Mirror
   */
  def staticClass(fullName: String): U#ClassSymbol

  /** The symbol corresponding to the globally accessible object with the
   *  given fully qualified name `fullName`.
   *
   *  To be consistent with Scala name resolution rules, in case of ambiguity between
   *  a package and an object, the object is never been considered.
   *
   *  For example for the following code:
   *
   *    package foo {
   *      object B
   *    }
   *
   *    object foo {
   *      object A
   *      object B
   *    }
   *
   *  staticModule("foo.B") will resolve to the symbol corresponding to the object B declared in the package foo, and
   *  staticModule("foo.A") will throw a ScalaReflectionException
   *
   *  In the example above, to load a symbol that corresponds to the object B declared in the object foo,
   *  use staticModule("foo") to load the module symbol and then navigate info.members of its moduleClass.
   *  @group Mirror
   */
  def staticModule(fullName: String): U#ModuleSymbol

  /** The symbol corresponding to a package with the
   *  given fully qualified name `fullName`.
   *  @group Mirror
   */
  def staticPackage(fullName: String): U#ModuleSymbol

  /**
   * Shortcut for `implicitly[WeakTypeTag[T]].tpe`
   * @group TypeTags
   */
  def weakTypeOf[T: universe.WeakTypeTag]: U#Type = universe.weakTypeTag[T].in(this).tpe

  /**
   * Shortcut for `implicitly[TypeTag[T]].tpe`
   * @group TypeTags
   */
  def typeOf[T: universe.TypeTag]: U#Type = universe.typeTag[T].in(this).tpe

  /**
   * Type symbol of `x` as derived from a type tag.
   * @group TypeTags
   */
  def symbolOf[T: universe.WeakTypeTag]: U#TypeSymbol
}