constructors.scala
来自「JAVA 语言的函数式编程扩展」· SCALA 代码 · 共 225 行
SCALA
225 行
/* NSC -- new Scala compiler * Copyright 2005-2007 LAMP/EPFL * @author */// $Id: Constructors.scala 13719 2008-01-17 16:37:27Z odersky $package scala.tools.nsc.transformimport scala.collection.mutable.ListBufferimport symtab.Flags._import util.TreeSetabstract class Constructors extends Transform { import global._ import definitions._ import posAssigner.atPos /** the following two members override abstract members in Transform */ val phaseName: String = "constructors" protected def newTransformer(unit: CompilationUnit): Transformer = new ConstructorTransformer class ConstructorTransformer extends Transformer { def transformClassTemplate(impl: Template): Template = { val clazz = impl.symbol.owner val stats = impl.body val localTyper = typer.atOwner(impl, clazz) var constr: DefDef = null var constrParams: List[Symbol] = null var constrBody: Block = null // decompose primary constructor into the three entities above. for (stat <- stats) { stat match { case ddef @ DefDef(_, _, _, List(vparams), _, rhs @ Block(_, Literal(_))) => if (ddef.symbol.isPrimaryConstructor) { constr = ddef constrParams = vparams map (_.symbol) constrBody = rhs } case _ => } } assert((constr ne null) && (constrBody ne null), impl) val paramAccessors = clazz.constrParamAccessors def parameter(acc: Symbol): Symbol = parameterNamed(nme.getterName(acc.originalName)) def parameterNamed(name: Name): Symbol = { def matchesName(param: Symbol) = param.name == name || param.name.startsWith(name) && param.name(name.length) == '$' val ps = constrParams filter matchesName if (ps.isEmpty) assert(false, "" + name + " not in " + constrParams) ps.head } var thisRefSeen: Boolean = false val intoConstructorTransformer = new Transformer { override def transform(tree: Tree): Tree = tree match { case Apply(Select(This(_), _), List()) => if ((tree.symbol hasFlag PARAMACCESSOR) && tree.symbol.owner == clazz) gen.mkAttributedIdent(parameter(tree.symbol.accessed)) setPos tree.pos else if (tree.symbol.outerSource == clazz && !clazz.isImplClass) gen.mkAttributedIdent(parameterNamed(nme.OUTER)) setPos tree.pos else super.transform(tree) case Select(This(_), _) if ((tree.symbol hasFlag PARAMACCESSOR) && !tree.symbol.isSetter && tree.symbol.owner == clazz) => gen.mkAttributedIdent(parameter(tree.symbol)) setPos tree.pos case Select(_, _) => thisRefSeen = true super.transform(tree) case This(_) => thisRefSeen = true super.transform(tree) case Super(_, _) => thisRefSeen = true super.transform(tree) case _ => super.transform(tree) } } def intoConstructor(oldowner: Symbol, tree: Tree) = intoConstructorTransformer.transform( new ChangeOwnerTraverser(oldowner, constr.symbol)(tree)) def canBeMoved(tree: Tree) = tree match { //todo: eliminate thisRefSeen case ValDef(mods, _, _, _) => (mods hasFlag PRESUPER | PARAMACCESSOR) || !thisRefSeen case _ => false } def mkAssign(to: Symbol, from: Tree): Tree = atPos(to.pos) { localTyper.typed { Assign(Select(This(clazz), to), from) } } def copyParam(to: Symbol, from: Symbol): Tree = { var result = mkAssign(to, Ident(from)) if (from.name == nme.OUTER) result = atPos(to.pos) { localTyper.typed { If(Apply(Select(Ident(from), nme.eq), List(Literal(Constant(null)))), Throw(New(TypeTree(NullPointerExceptionClass.tpe), List(List()))), result); } } result } val defBuf = new ListBuffer[Tree] val constrStatBuf = new ListBuffer[Tree] val constrPrefixBuf = new ListBuffer[Tree] val presupers = treeInfo.preSuperFields(stats) for (stat <- constrBody.stats) { constrStatBuf += stat stat match { case ValDef(mods, name, _, _) if (mods hasFlag PRESUPER) => constrStatBuf += localTyper.typed { atPos(stat.pos) { val fields = presupers filter ( vdef => nme.localToGetter(vdef.name) == name) assert(fields.length == 1) Assign( gen.mkAttributedRef(clazz.thisType, fields.head.symbol), Ident(stat.symbol)) } } case _ => } } for (stat <- stats) stat match { case DefDef(mods, name, tparams, vparamss, tpt, rhs) => stat.symbol.tpe match { case MethodType(List(), tp @ ConstantType(c)) => defBuf += copy.DefDef( stat, mods, name, tparams, vparamss, tpt, Literal(c) setPos rhs.pos setType tp) case _ => if (!stat.symbol.isPrimaryConstructor) defBuf += stat } case ValDef(mods, name, tpt, rhs) => if (stat.symbol.tpe.isInstanceOf[ConstantType]) assert(stat.symbol.getter(stat.symbol.owner) != NoSymbol, stat) else { try { if (rhs != EmptyTree && !stat.symbol.hasFlag(LAZY)) { val rhs1 = intoConstructor(stat.symbol, rhs); (if (canBeMoved(stat)) constrPrefixBuf else constrStatBuf) += mkAssign( stat.symbol, rhs1) } defBuf += copy.ValDef(stat, mods, name, tpt, EmptyTree) } catch { case ex: Throwable => println("error when transforming "+stat+" in "+stats) throw ex } } case ClassDef(_, _, _, _) => defBuf += (new ConstructorTransformer).transform(stat) case _ => constrStatBuf += intoConstructor(impl.symbol, stat) } val accessed = new TreeSet[Symbol]((x, y) => x isLess y) def isAccessed(sym: Symbol) = sym.owner != clazz || !(sym hasFlag PARAMACCESSOR) || !sym.isPrivateLocal || (accessed contains sym) val accessTraverser = new Traverser { override def traverse(tree: Tree) = { tree match { case Select(_, _) => if (!isAccessed(tree.symbol)) accessed addEntry tree.symbol case _ => } super.traverse(tree) } } for (stat <- defBuf.elements) accessTraverser.traverse(stat) val paramInits = for (acc <- paramAccessors if isAccessed(acc)) yield copyParam(acc, parameter(acc)) defBuf += copy.DefDef( constr, constr.mods, constr.name, constr.tparams, constr.vparamss, constr.tpt, copy.Block( constrBody, paramInits ::: constrPrefixBuf.toList ::: constrStatBuf.toList, constrBody.expr)); for (sym <- clazz.info.decls.toList) if (!isAccessed(sym)) clazz.info.decls unlink sym copy.Template(impl, impl.parents, impl.self, defBuf.toList filter (stat => isAccessed(stat.symbol))) } override def transform(tree: Tree): Tree = tree match { case ClassDef(mods, name, tparams, impl) if !tree.symbol.hasFlag(INTERFACE) => copy.ClassDef(tree, mods, name, tparams, transformClassTemplate(impl)) case _ => super.transform(tree) } } // ConstructorTransformer}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?