summaryrefslogtreecommitdiff
path: root/src/compiler/scala/reflect/macros/contexts/Enclosures.scala
blob: 5e931817b557b4838e9d2fa1105fba1746bf2df6 (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
package scala.reflect.macros
package contexts

import scala.reflect.{ClassTag, classTag}

trait Enclosures {
  self: Context =>

  import universe._

  private lazy val site       = callsiteTyper.context
  private lazy val enclTrees  = site.enclosingContextChain map (_.tree)
  private lazy val enclPoses  = enclosingMacros map (_.macroApplication.pos) filterNot (_ eq NoPosition)

  private def lenientEnclosure[T <: Tree : ClassTag]: Tree = enclTrees collectFirst { case x: T => x } getOrElse EmptyTree
  private def strictEnclosure[T <: Tree : ClassTag]: T = enclTrees collectFirst { case x: T => x } getOrElse (throw new EnclosureException(classTag[T].runtimeClass, enclTrees))

  // vals are eager to simplify debugging
  // after all we wouldn't save that much time by making them lazy
  val macroApplication: Tree                      = expandee
  def enclosingPackage: PackageDef                = strictEnclosure[PackageDef]
  val enclosingClass: Tree                        = lenientEnclosure[ImplDef]
  def enclosingImpl: ImplDef                      = strictEnclosure[ImplDef]
  def enclosingTemplate: Template                 = strictEnclosure[Template]
  val enclosingImplicits: List[ImplicitCandidate] = site.openImplicits.map(_.toImplicitCandidate)
  val enclosingMacros: List[Context]              = this :: universe.analyzer.openMacros // include self
  val enclosingMethod: Tree                       = lenientEnclosure[DefDef]
  def enclosingDef: DefDef                        = strictEnclosure[DefDef]
  val enclosingPosition: Position                 = if (enclPoses.isEmpty) NoPosition else enclPoses.head.pos
  val enclosingUnit: CompilationUnit              = universe.currentRun.currentUnit
  val enclosingRun: Run                           = universe.currentRun
}