superaccessors.scala

来自「JAVA 语言的函数式编程扩展」· SCALA 代码 · 共 440 行 · 第 1/2 页

SCALA
440
字号
/* NSC -- new Scala compiler * Copyright 2005-2006 LAMP/EPFL * @author Martin Odersky */// $Id: SuperAccessors.scala 14105 2008-02-22 13:14:54Z odersky $package scala.tools.nsc.typecheckerimport scala.collection.mutable.ListBufferimport nsc.symtab.Flags._import scala.tools.nsc.util.{Position}/** This phase adds super accessors for all super calls that *  either appear in a trait or have as a target a member of some outer class. *  It also replaces references to parameter accessors with aliases by super *  references to these aliases. *  The phase also checks that symbols accessed from super are not abstract, *  or are overridden by an abstract override. *  Finally, the phase also mangles the names of class-members which are private *  up to an enclosing non-package class, in order to avoid overriding conflicts. * *  @author  Martin Odersky *  @version 1.0 */abstract class SuperAccessors extends transform.Transform with transform.TypingTransformers {  // inherits abstract value `global' and class `Phase' from Transform  import global._  import posAssigner.atPos  import typer.typed  /** the following two members override abstract members in Transform */  val phaseName: String = "superaccessors"  protected def newTransformer(unit: CompilationUnit): Transformer =    new SuperAccTransformer(unit)  class SuperAccTransformer(unit: CompilationUnit) extends TypingTransformer(unit) {    private var validCurrentOwner = true    private var accDefs: List[(Symbol, ListBuffer[Tree])] = List()    private val typer = analyzer.newTyper(analyzer.rootContext(unit))    private def accDefBuf(clazz: Symbol) =      accDefs.dropWhile(_._1 != clazz).head._2/*    private def transformArgs(args: List[Tree], formals: List[Type]) = {      if (!formals.isEmpty && formals.last.symbol == definitions.ByNameParamClass)        ((args take (formals.length - 1) map transform) :::         withInvalidOwner { args drop (formals.length - 1) map transform })      else        args map transform    }*/    private def transformArgs(args: List[Tree], formals: List[Type]) =      List.map2(args, formals){ (arg, formal) =>        if (formal.typeSymbol == definitions.ByNameParamClass)           withInvalidOwner { checkPackedConforms(transform(arg), formal.typeArgs.head) }        else transform(arg)      } :::      (args drop formals.length map transform)    private def checkPackedConforms(tree: Tree, pt: Type): Tree = {      if (tree.tpe exists (_.typeSymbol.isExistentialSkolem)) {        val packed = typer.packedType(tree, NoSymbol)        if (!(packed <:< pt)) typer.infer.typeError(tree.pos, packed, pt)      }      tree    }    /** Check that a class and its companion object to not both define     *  a class or module with same name     */    private def checkCompanionNameClashes(sym: Symbol) =      if (!sym.owner.isModuleClass) {        val linked = sym.owner.linkedClassOfClass        if (linked != NoSymbol) {          var other = linked.info.decl(sym.name.toTypeName).filter(_.isClass)          if (other == NoSymbol)            other = linked.info.decl(sym.name.toTermName).filter(_.isModule)          if (other != NoSymbol)            unit.error(sym.pos, "name clash: "+sym.owner+" defines "+sym+                       "\nand its companion "+sym.owner.linkedModuleOfClass+" also defines "+                       other)        }      }    private def transformSuperSelect(tree: Tree) = tree match {      case Select(sup @ Super(_, mix), name) =>        val sym = tree.symbol        val clazz = sup.symbol        if (sym.isDeferred) {          val member = sym.overridingSymbol(clazz);          if (mix != nme.EMPTY.toTypeName || member == NoSymbol ||               !((member hasFlag ABSOVERRIDE) && member.isIncompleteIn(clazz)))            unit.error(tree.pos, ""+sym+sym.locationString+" is accessed from super. It may not be abstract "+                                 "unless it is overridden by a member declared `abstract' and `override'");        }        if (tree.isTerm && mix == nme.EMPTY.toTypeName &&             (clazz.isTrait || clazz != currentOwner.enclClass || !validCurrentOwner)) {          val supername = nme.superName(sym.name)          var superAcc = clazz.info.decl(supername).suchThat(_.alias == sym)          if (superAcc == NoSymbol) {            if (settings.debug.value) log("add super acc " + sym + sym.locationString + " to `" + clazz);//debug            superAcc =               clazz.newMethod(tree.pos, supername)                .setFlag(SUPERACCESSOR | PRIVATE)                .setAlias(sym)            var superAccTpe = clazz.thisType.memberType(sym)             if (sym.isModule && !sym.isMethod) {              // the super accessor always needs to be a method. See #231              superAccTpe = PolyType(List(), superAccTpe)            }            superAcc.setInfo(superAccTpe.cloneInfo(superAcc))            //println("creating super acc "+superAcc+":"+superAcc.tpe)//DEBUG            clazz.info.decls enter superAcc;            accDefBuf(clazz) += typed(DefDef(superAcc, vparamss => EmptyTree))          }          atPos(sup.pos) {            Select(gen.mkAttributedThis(clazz), superAcc) setType tree.tpe;          }        } else {          tree        }      case _ =>        assert(tree.tpe.isError, tree)        tree    }     override def transform(tree: Tree): Tree = try { tree match {      case ClassDef(_, _, _, _) =>        checkCompanionNameClashes(tree.symbol)        val decls = tree.symbol.info.decls        for (val sym <- decls.toList) {          if (sym.privateWithin.isClass && !sym.privateWithin.isModuleClass &&              !sym.hasFlag(EXPANDEDNAME) && !sym.isConstructor) {            decls.unlink(sym)            sym.expandName(sym.privateWithin)            decls.enter(sym)          }        }        super.transform(tree)      case ModuleDef(_, _, _) =>        checkCompanionNameClashes(tree.symbol)        super.transform(tree)      case Template(parents, self, body) =>	val ownAccDefs = new ListBuffer[Tree];	accDefs = (currentOwner, ownAccDefs) :: accDefs;                // ugly hack... normally, the following line should not be         // necessary, the 'super' method taking care of that. but because        // that one is iterating through parents (and we dont want that here)        // we need to inline it.        curTree = tree        val body1 = atOwner(currentOwner) { transformTrees(body) }	accDefs = accDefs.tail;	copy.Template(tree, parents, self, ownAccDefs.toList ::: body1);      case TypeApply(sel @ Select(This(_), name), args) =>        val sym = tree.symbol        if (needsProtectedAccessor(sym, tree.pos)) {          if (settings.debug.value) log("Adding protected accessor for " + tree);          transform(makeAccessor(sel.asInstanceOf[Select], args))        } else           tree            case Select(qual @ This(_), name) =>        val sym = tree.symbol         if ((sym hasFlag PARAMACCESSOR) && (sym.alias != NoSymbol)) {          val result = typed {            Select(              Super(qual.symbol, nme.EMPTY.toTypeName/*qual.symbol.info.parents.head.symbol.name*/) setPos qual.pos,              sym.alias) setPos tree.pos          }          if (settings.debug.value)             Console.println("alias replacement: " + tree + " ==> " + result);//debug          transformSuperSelect(result)        } else {          if (needsProtectedAccessor(sym, tree.pos)) {            if (settings.debug.value) log("Adding protected accessor for " + tree);            transform(makeAccessor(tree.asInstanceOf[Select], List(EmptyTree)))          } else             tree        }      case Select(sup @ Super(_, mix), name) =>        val sym = tree.symbol        if (sym.isValue && !sym.isMethod || sym.hasFlag(ACCESSOR)) {          unit.error(tree.pos, "super may be not be used on "+sym)        }        transformSuperSelect(tree)            case TypeApply(sel @ Select(qual, name), args) =>        val sym = tree.symbol        if (needsProtectedAccessor(sym, tree.pos)) {          if (settings.debug.value) log("Adding protected accessor for tree: " + tree);          transform(makeAccessor(sel.asInstanceOf[Select], args))        } else          super.transform(tree)      case Select(qual, name) =>        val sym = tree.symbol        if (needsProtectedAccessor(sym, tree.pos)) {          if (settings.debug.value) log("Adding protected accessor for tree: " + tree);          transform(makeAccessor(tree.asInstanceOf[Select], List(EmptyTree)))        } else          super.transform(tree)                      case Assign(lhs @ Select(qual, name), rhs) =>        if (lhs.symbol.isVariable &&             lhs.symbol.hasFlag(JAVA) &&            needsProtectedAccessor(lhs.symbol, tree.pos)) {          if (settings.debug.value) log("Adding protected setter for " + tree)          val setter = makeSetter(lhs);          if (settings.debug.value)            log("Replaced " + tree + " with " + setter);          transform(typed(Apply(setter, List(qual, rhs))))        } else          super.transform(tree)      case Apply(fn, args) =>        assert(fn.tpe != null) 

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?