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 + -
显示快捷键?