package scala package reflect package macros import scala.language.implicitConversions import scala.language.higherKinds /** * EXPERIMENTAL * * The refinement of [[scala.reflect.api.Universe]] for the use by macro writers. * * This universe provides mutability for reflection artifacts (e.g. macros can change types of compiler trees, * add annotation to symbols representing definitions, etc) and exposes some internal compiler functionality * such as `Symbol.deSkolemize` or `Tree.attachments`. * @groupname Macros Macro Specific Additions * @groupprio Macros -1 * * @contentDiagram hideNodes "*Api" */ abstract class Universe extends scala.reflect.api.Universe { /** @inheritdoc */ override type Internal <: MacroInternalApi /** @inheritdoc */ trait MacroInternalApi extends InternalApi { internal => /** Adds a given symbol to the given scope. */ def enter(scope: Scope, sym: Symbol): scope.type /** Removes a given symbol to the given scope. */ def unlink(scope: Scope, sym: Symbol): scope.type /** Collects all the symbols defined by subtrees of `tree` that are owned by `prev`, * and then changes their owner to point to `next`. * * This is an essential tool to battle owner chain corruption when moving trees * from one lexical context to another. Whenever you take an attributed tree that * has been typechecked under the Context owned by some symbol (let's call it `x`) * and splice it elsewhere, into the Context owned by another symbol (let's call it `y`), * it is imperative that you either call `untypecheck` or do `changeOwner(tree, x, y)`. * * Since at the moment `untypecheck` has fundamental problem that can sometimes lead to tree corruption, * `changeOwner` becomes an indispensable tool in building 100% robust macros. * Future versions of the reflection API might obviate the need in taking care of * these low-level details, but at the moment this is what we've got. */ def changeOwner(tree: Tree, prev: Symbol, next: Symbol): tree.type /** Advanced tree factories */ val gen: TreeGen /** The attachment of the symbol. */ def attachments(symbol: Symbol): Attachments { type Pos = Position } /** Updates the attachment with the payload slot of T added/updated with the provided value. * Replaces an existing payload of the same type, if exists. * Returns the symbol itself. */ def updateAttachment[T: ClassTag](symbol: Symbol, attachment: T): symbol.type /** Update the attachment with the payload of the given class type `T` removed. * Returns the symbol itself. */ def removeAttachment[T: ClassTag](symbol: Symbol): symbol.type /** Sets the `owner` of the symbol. */ def setOwner(symbol: Symbol, newowner: Symbol): symbol.type /** Sets the `info` of the symbol. */ def setInfo(symbol: Symbol, tpe: Type): symbol.type /** Sets the `annotations` of the symbol. */ def setAnnotations(symbol: Symbol, annots: Annotation*): symbol.type /** Sets the `name` of the symbol. */ def setName(symbol: Symbol, name: Name): symbol.type /** Sets the `privateWithin` of the symbol. */ def setPrivateWithin(symbol: Symbol, sym: Symbol): symbol.type /** Enables `flags` on the symbol. */ def setFlag(symbol: Symbol, flags: FlagSet): symbol.type /** Disables `flags` on the symbol. */ def resetFlag(symbol: Symbol, flags: FlagSet): symbol.type /** The attachment of the tree. */ def attachments(tree: Tree): Attachments { type Pos = Position } /** Updates the attachment with the payload slot of T added/updated with the provided value. * Replaces an existing payload of the same type, if exists. * Returns the tree itself. */ def updateAttachment[T: ClassTag](tree: Tree, attachment: T): tree.type /** Update the attachment with the payload of the given class type `T` removed. * Returns the tree itself. */ def removeAttachment[T: ClassTag](tree: Tree): tree.type /** Sets the `pos` of the tree. Returns the tree itself. */ def setPos(tree: Tree, newpos: Position): tree.type /** Sets the `tpe` of the tree. Returns the tree itself. */ def setType(tree: Tree, tp: Type): tree.type /** Like `setType`, but if this is a previously empty TypeTree that * fact is remembered so that `untypecheck` will snap back. * * \@PP: Attempting to elaborate on the above, I find: If defineType * is called on a TypeTree whose type field is null or NoType, * this is recorded as "wasEmpty = true". That value is used in * ResetAttrsTraverser, which nulls out the type field of TypeTrees * for which wasEmpty is true, leaving the others alone. * * `untypecheck` (or `resetAttrs` in compiler parlance) is used * in situations where some speculative * typing of a tree takes place, fails, and the tree needs to be * returned to its former state to try again. So according to me: * using `defineType` instead of `setType` is how you communicate * that the type being set does not depend on any previous state, * and therefore should be abandoned if the current line of type * inquiry doesn't work out. */ def defineType(tree: Tree, tp: Type): tree.type /** Sets the `symbol` of the tree. Returns the tree itself. */ def setSymbol(tree: Tree, sym: Symbol): tree.type /** Sets the `original` field of the type tree. */ def setOriginal(tt: TypeTree, original: Tree): TypeTree /** Mark a variable as captured; i.e. force boxing in a *Ref type. * @group Macros */ def captureVariable(vble: Symbol): Unit /** Mark given identifier as a reference to a captured variable itself * suppressing dereferencing with the `elem` field. * @group Macros */ def referenceCapturedVariable(vble: Symbol): Tree /** Convert type of a captured variable to *Ref type. * @group Macros */ def capturedVariableType(vble: Symbol): Type /** Retrieves the untyped list of subpatterns attached to selector dummy of an UnApply node. * Useful in writing quasiquoting macros that do pattern matching. */ def subpatterns(tree: Tree): Option[List[Tree]] /** @inheritdoc */ override type Decorators <: MacroDecoratorApi /** @inheritdoc */ trait MacroDecoratorApi extends DecoratorApi { /** Extension methods for scopes */ type ScopeDecorator[T <: Scope] <: MacroScopeDecoratorApi[T] /** @see [[ScopeDecorator]] */ implicit def scopeDecorator[T <: Scope](tree: T): ScopeDecorator[T] /** @see [[ScopeDecorator]] */ class MacroScopeDecoratorApi[T <: Scope](val scope: T) { /** @see [[internal.enter]] */ def enter(sym: Symbol): T = internal.enter(scope, sym) /** @see [[internal.unlink]] */ def unlink(sym: Symbol): T = internal.unlink(scope, sym) } /** @inheritdoc */ override type TreeDecorator[T <: Tree] <: MacroTreeDecoratorApi[T] /** @see [[TreeDecorator]] */ class MacroTreeDecoratorApi[T <: Tree](override val tree: T) extends TreeDecoratorApi[T](tree) { /** @see [[internal.changeOwner]] */ def changeOwner(prev: Symbol, next: Symbol): tree.type = internal.changeOwner(tree, prev, next) /** @see [[internal.attachments]] */ def attachments: Attachments { type Pos = Position } = internal.attachments(tree) /** @see [[internal.updateAttachment]] */ def updateAttachment[A: ClassTag](attachment: A): tree.type = internal.updateAttachment(tree, attachment) /** @see [[internal.removeAttachment]] */ def removeAttachment[A: ClassTag]: T = internal.removeAttachment[A](tree) /** @see [[internal.setPos]] */ def setPos(newpos: Position): T = internal.setPos(tree, newpos) /** @see [[internal.setType]] */ def setType(tp: Type): T = internal.setType(tree, tp) /** @see [[internal.defineType]] */ def defineType(tp: Type): T = internal.defineType(tree, tp) /** @see [[internal.setSymbol]] */ def setSymbol(sym: Symbol): T = internal.setSymbol(tree, sym) } /** Extension methods for typetrees */ type TypeTreeDecorator[T <: TypeTree] <: MacroTypeTreeDecoratorApi[T] /** @see [[TypeTreeDecorator]] */ implicit def typeTreeDecorator[T <: TypeTree](tt: T): TypeTreeDecorator[T] /** @see [[TypeTreeDecorator]] */ class MacroTypeTreeDecoratorApi[T <: TypeTree](val tt: T) { /** @see [[internal.setOriginal]] */ def setOriginal(tree: Tree): TypeTree = internal.setOriginal(tt, tree) } /** @inheritdoc */ override type SymbolDecorator[T <: Symbol] <: MacroSymbolDecoratorApi[T] /** @see [[TreeDecorator]] */ class MacroSymbolDecoratorApi[T <: Symbol](override val symbol: T) extends SymbolDecoratorApi[T](symbol) { /** @see [[internal.attachments]] */ def attachments: Attachments { type Pos = Position } = internal.attachments(symbol) /** @see [[internal.updateAttachment]] */ def updateAttachment[A: ClassTag](attachment: A): T = internal.updateAttachment(symbol, attachment) /** @see [[internal.removeAttachment]] */ def removeAttachment[A: ClassTag]: T = internal.removeAttachment[A](symbol) /** @see [[internal.setOwner]] */ def setOwner(newowner: Symbol): T = internal.setOwner(symbol, newowner) /** @see [[internal.setInfo]] */ def setInfo(tpe: Type): T = internal.setInfo(symbol, tpe) /** @see [[internal.setAnnotations]] */ def setAnnotations(annots: Annotation*): T = internal.setAnnotations(symbol, annots: _*) /** @see [[internal.setName]] */ def setName(name: Name): T = internal.setName(symbol, name) /** @see [[internal.setPrivateWithin]] */ def setPrivateWithin(sym: Symbol): T = internal.setPrivateWithin(symbol, sym) /** @see [[internal.setFlag]] */ def setFlag(flags: FlagSet): T = internal.setFlag(symbol, flags) /** @see [[internal.setFlag]] */ def resetFlag(flags: FlagSet): T = internal.resetFlag(symbol, flags) } } } /** @group Internal */ trait TreeGen { /** Builds a reference to value whose type is given stable prefix. * The type must be suitable for this. For example, it * must not be a TypeRef pointing to an abstract type variable. */ def mkAttributedQualifier(tpe: Type): Tree /** Builds a reference to value whose type is given stable prefix. * If the type is unsuitable, e.g. it is a TypeRef for an * abstract type variable, then an Ident will be made using * termSym as the Ident's symbol. In that case, termSym must * not be NoSymbol. */ def mkAttributedQualifier(tpe: Type, termSym: Symbol): Tree /** Builds a typed reference to given symbol with given stable prefix. */ def mkAttributedRef(pre: Type, sym: Symbol): RefTree /** Builds a typed reference to given symbol. */ def mkAttributedRef(sym: Symbol): RefTree def stabilize(tree: Tree): Tree def mkAttributedStableRef(pre: Type, sym: Symbol): Tree def mkAttributedStableRef(sym: Symbol): Tree /** Builds an untyped reference to given symbol. Requires the symbol to be static. */ def mkUnattributedRef(sym: Symbol): RefTree /** Builds an untyped reference to symbol with given name. Requires the symbol to be static. */ def mkUnattributedRef(fullName: Name): RefTree /** Builds a typed This reference to given symbol. */ def mkAttributedThis(sym: Symbol): This /** Builds a typed Ident with an underlying symbol. */ def mkAttributedIdent(sym: Symbol): RefTree /** Builds a typed Select with an underlying symbol. */ def mkAttributedSelect(qual: Tree, sym: Symbol): RefTree /** A creator for method calls, e.g. fn[T1, T2, ...](v1, v2, ...) * There are a number of variations. * * @param receiver symbol of the method receiver * @param methodName name of the method to call * @param targs type arguments (if Nil, no TypeApply node will be generated) * @param args value arguments * @return the newly created trees. */ def mkMethodCall(receiver: Symbol, methodName: Name, targs: List[Type], args: List[Tree]): Tree def mkMethodCall(method: Symbol, targs: List[Type], args: List[Tree]): Tree def mkMethodCall(method: Symbol, args: List[Tree]): Tree def mkMethodCall(target: Tree, args: List[Tree]): Tree def mkMethodCall(receiver: Symbol, methodName: Name, args: List[Tree]): Tree def mkMethodCall(receiver: Tree, method: Symbol, targs: List[Type], args: List[Tree]): Tree def mkMethodCall(target: Tree, targs: List[Type], args: List[Tree]): Tree def mkNullaryCall(method: Symbol, targs: List[Type]): Tree /** A tree that refers to the runtime reflexive universe, `scala.reflect.runtime.universe`. */ def mkRuntimeUniverseRef: Tree def mkZero(tp: Type): Tree def mkCast(tree: Tree, pt: Type): Tree } /** @see [[internal.gen]] */ @deprecated("use `internal.gen` instead", "2.11.0") val treeBuild: TreeGen /** @inheritdoc */ type Compat <: MacroCompatApi /** @see [[compat]] * @group Internal */ trait MacroCompatApi extends CompatApi { /** Scala 2.10 compatibility enrichments for Symbol. */ implicit class MacroCompatibleSymbol(symbol: Symbol) { /** @see [[InternalMacroApi.attachments]] */ @deprecated("use `internal.attachments` instead or import `internal.decorators._` for infix syntax", "2.11.0") def attachments: Attachments { type Pos = Position } = internal.attachments(symbol) /** @see [[InternalMacroApi.updateAttachment]] */ @deprecated("use `internal.updateAttachment` instead or import `internal.decorators._` for infix syntax", "2.11.0") def updateAttachment[T: ClassTag](attachment: T): Symbol = internal.updateAttachment[T](symbol, attachment) /** @see [[InternalMacroApi.removeAttachment]] */ @deprecated("use `internal.removeAttachment` instead or import `internal.decorators._` for infix syntax", "2.11.0") def removeAttachment[T: ClassTag]: Symbol = internal.removeAttachment[T](symbol) /** @see [[InternalMacroApi.setInfo]] */ @deprecated("use `internal.setInfo` instead or import `internal.decorators._` for infix syntax", "2.11.0") def setTypeSignature(tpe: Type): Symbol = internal.setInfo(symbol, tpe) /** @see [[InternalMacroApi.setAnnotations]] */ @deprecated("use `internal.setAnnotations` instead or import `internal.decorators._` for infix syntax", "2.11.0") def setAnnotations(annots: Annotation*): Symbol = internal.setAnnotations(symbol, annots: _*) /** @see [[InternalMacroApi.setName]] */ @deprecated("use `internal.setName` instead or import `internal.decorators._` for infix syntax", "2.11.0") def setName(name: Name): Symbol = internal.setName(symbol, name) /** @see [[InternalMacroApi.setPrivateWithin]] */ @deprecated("use `internal.setPrivateWithin` instead or import `internal.decorators._` for infix syntax", "2.11.0") def setPrivateWithin(sym: Symbol): Symbol = internal.setPrivateWithin(symbol, sym) } /** Scala 2.10 compatibility enrichments for TypeTree. */ implicit class MacroCompatibleTree(tree: Tree) { /** @see [[InternalMacroApi.attachments]] */ @deprecated("use `internal.attachments` instead or import `internal.decorators._` for infix syntax", "2.11.0") def attachments: Attachments { type Pos = Position } = internal.attachments(tree) /** @see [[InternalMacroApi.updateAttachment]] */ @deprecated("use `internal.updateAttachment` instead or import `internal.decorators._` for infix syntax", "2.11.0") def updateAttachment[T: ClassTag](attachment: T): Tree = internal.updateAttachment[T](tree, attachment) /** @see [[InternalMacroApi.removeAttachment]] */ @deprecated("use `internal.removeAttachment` instead or import `internal.decorators._` for infix syntax", "2.11.0") def removeAttachment[T: ClassTag]: Tree = internal.removeAttachment[T](tree) /** @see [[InternalMacroApi.setPos]] */ @deprecated("use `internal.setPos` instead or import `internal.decorators._` for infix syntax", "2.11.0") def pos_=(pos: Position): Unit = internal.setPos(tree, pos) /** @see [[InternalMacroApi.setPos]] */ @deprecated("use `internal.setPos` instead or import `internal.decorators._` for infix syntax", "2.11.0") def setPos(newpos: Position): Tree = internal.setPos(tree, newpos) /** @see [[InternalMacroApi.setType]] */ @deprecated("use `internal.setType` instead or import `internal.decorators._` for infix syntax", "2.11.0") def tpe_=(t: Type): Unit = internal.setType(tree, t) /** @see [[InternalMacroApi.setType]] */ @deprecated("use `internal.setType` instead or import `internal.decorators._` for infix syntax", "2.11.0") def setType(tp: Type): Tree = internal.setType(tree, tp) /** @see [[InternalMacroApi.defineType]] */ @deprecated("use `internal.defineType` instead or import `internal.decorators._` for infix syntax", "2.11.0") def defineType(tp: Type): Tree = internal.defineType(tree, tp) /** @see [[InternalMacroApi.setSymbol]] */ @deprecated("use `internal.setSymbol` instead or import `internal.decorators._` for infix syntax", "2.11.0") def symbol_=(sym: Symbol): Unit = internal.setSymbol(tree, sym) /** @see [[InternalMacroApi.setSymbol]] */ @deprecated("use `internal.setSymbol` instead or import `internal.decorators._` for infix syntax", "2.11.0") def setSymbol(sym: Symbol): Tree = internal.setSymbol(tree, sym) } /** Scala 2.10 compatibility enrichments for TypeTree. */ implicit class CompatibleTypeTree(tt: TypeTree) { /** @see [[InternalMacroApi.setOriginal]] */ @deprecated("use `internal.setOriginal` instead or import `internal.decorators._` for infix syntax", "2.11.0") def setOriginal(tree: Tree): TypeTree = internal.setOriginal(tt, tree) } /** @see [[InternalMacroApi.captureVariable]] */ @deprecated("use `internal.captureVariable` instead", "2.11.0") def captureVariable(vble: Symbol): Unit = internal.captureVariable(vble) /** @see [[InternalMacroApi.captureVariable]] */ @deprecated("use `internal.referenceCapturedVariable` instead", "2.11.0") def referenceCapturedVariable(vble: Symbol): Tree = internal.referenceCapturedVariable(vble) /** @see [[InternalMacroApi.captureVariable]] */ @deprecated("use `internal.capturedVariableType` instead", "2.11.0") def capturedVariableType(vble: Symbol): Type = internal.capturedVariableType(vble) } /** The type of compilation runs. * @see [[scala.reflect.macros.Enclosures]] * @template * @group Macros */ @deprecated("c.enclosingTree-style APIs are now deprecated; consult the scaladoc for more information", "2.11.0") type Run <: RunContextApi /** Compilation run uniquely identifies current invocation of the compiler * (e.g. can be used to implement per-run caches for macros) and provides access to units of work * of the invocation (currently processed unit of work and the list of all units). * @see [[scala.reflect.macros.Enclosures]] * @group API */ @deprecated("c.enclosingTree-style APIs are now deprecated; consult the scaladoc for more information", "2.11.0") trait RunContextApi { /** Currently processed unit of work (a real or a virtual file). */ @deprecated("c.enclosingTree-style APIs are now deprecated; consult the scaladoc for more information", "2.11.0") def currentUnit: CompilationUnit /** All units of work comprising this compilation run. */ @deprecated("c.enclosingTree-style APIs are now deprecated; consult the scaladoc for more information", "2.11.0") def units: Iterator[CompilationUnit] } /** The type of compilation units. * @see [[scala.reflect.macros.Enclosures]] * @template * @group Macros */ @deprecated("c.enclosingTree-style APIs are now deprecated; consult the scaladoc for more information", "2.11.0") type CompilationUnit <: CompilationUnitContextApi /** Compilation unit describes a unit of work of the compilation run. * It provides such information as file name, textual representation of the unit and the underlying AST. * @see [[scala.reflect.macros.Enclosures]] * @group API */ @deprecated("c.enclosingTree-style APIs are now deprecated; consult the scaladoc for more information", "2.11.0") trait CompilationUnitContextApi { /** Source file corresponding to this compilation unit. * * Exposes information about the file as a part of a real or virtual file system * along with the contents of that file. * * The return type is `scala.reflect.io.AbstractFile`, which belongs to an experimental part of Scala reflection. * It should not be used unless you know what you are doing. In subsequent releases, this API will be refined * and exposed as a part of scala.reflect.api. */ @deprecated("c.enclosingTree-style APIs are now deprecated; consult the scaladoc for more information", "2.11.0") def source: scala.reflect.internal.util.SourceFile /** The AST that corresponds to this compilation unit. */ @deprecated("c.enclosingTree-style APIs are now deprecated; consult the scaladoc for more information", "2.11.0") def body: Tree } }