blob: 41a0938b8ee56d5de2fb075cce3f0625a9d0b04e (
plain) (
tree)
|
|
package dotty.tools.dotc
package transform
import core._
import Types._
import Contexts._
import Symbols._
import SymDenotations._
import Decorators._
import Names._
import StdNames._
import NameOps._
import Flags._
import language.implicitConversions
object SymUtils {
implicit def decorateSymbol(sym: Symbol): SymUtils = new SymUtils(sym)
implicit def decorateSymDenot(d: SymDenotation): SymUtils = new SymUtils(d.symbol)
}
/** A decorator that provides methods on symbols
* that are needed in the transformer pipeline.
*/
class SymUtils(val self: Symbol) extends AnyVal {
import SymUtils._
def superClass(implicit ctx: Context) = {
val parents = self.asClass.classInfo.parents
if (parents.isEmpty) NoSymbol
else parents.head.symbol
}
/**
* For a class: All interfaces implemented by a class except for those inherited through the superclass.
* For a trait: all parent traits
*/
def superInterfaces(implicit ctx: Context) = {
val superCls = self.superClass
val baseClasses = self.asClass.baseClasses
if (baseClasses.isEmpty) Nil
else baseClasses.tail.takeWhile(_ ne superCls).reverse
}
/** All interfaces implemented by a class, except for those inherited through the superclass. */
def mixins(implicit ctx: Context) = {
if (self is Trait) Nil
else superInterfaces
}
def isTypeTestOrCast(implicit ctx: Context): Boolean =
self == defn.Any_asInstanceOf || self == defn.Any_isInstanceOf
def isVolatile(implicit ctx: Context) = self.hasAnnotation(defn.VolatileAnnot)
def isAnyOverride(implicit ctx: Context) = self.is(Override) || self.is(AbsOverride)
// careful: AbsOverride is a term only flag. combining with Override would catch only terms.
/** If this is a constructor, its owner: otherwise this. */
final def skipConstructor(implicit ctx: Context): Symbol =
if (self.isConstructor) self.owner else self
/** The logically enclosing method or class for this symbol.
* Instead of constructors one always picks the enclosing class.
*/
final def enclosure(implicit ctx: Context) = self.owner.enclosingMethod.skipConstructor
/** Apply symbol/symbol substitution to this symbol */
def subst(from: List[Symbol], to: List[Symbol]): Symbol = {
def loop(from: List[Symbol], to: List[Symbol]): Symbol =
if (from.isEmpty) self
else if (self eq from.head) to.head
else loop(from.tail, to.tail)
loop(from, to)
}
def accessorNamed(name: TermName)(implicit ctx: Context): Symbol =
self.owner.info.decl(name).suchThat(_ is Accessor).symbol
def termParamAccessors(implicit ctx: Context): List[Symbol] =
self.info.decls.filter(_ is TermParamAccessor).toList
def caseAccessors(implicit ctx:Context) =
self.info.decls.filter(_ is CaseAccessor).toList
def getter(implicit ctx: Context): Symbol =
if (self.isGetter) self else accessorNamed(self.asTerm.name.getterName)
def setter(implicit ctx: Context): Symbol =
if (self.isSetter) self
else accessorNamed(self.asTerm.name.setterName)
def field(implicit ctx: Context): Symbol =
self.owner.info.decl(self.asTerm.name.fieldName).suchThat(!_.is(Method)).symbol
/** `fullName` where `$' is the separator character */
def flatName(implicit ctx: Context): Name = self.flatName('$')
def initializer(implicit ctx: Context): TermSymbol =
self.owner.info.decl(InitializerName(self.asTerm.name)).symbol.asTerm
def isField(implicit ctx: Context): Boolean =
self.isTerm && !self.is(Method)
}
|