refchecks.scala
来自「JAVA 语言的函数式编程扩展」· SCALA 代码 · 共 841 行 · 第 1/3 页
SCALA
841 行
override def transformStats(stats: List[Tree], exprOwner: Symbol): List[Tree] = { pushLevel() enterSyms(stats) var index = -1 val stats1 = stats flatMap { stat => index += 1; transformStat(stat, index) } popLevel() stats1 } /** Implements lazy value accessors: * - for lazy values of type Unit and all lazy fields inside traits, * the rhs is the initializer itself * - for all other lazy values z the accessor is a block of this form: * { z = <rhs>; z } where z can be an identifier or a field. */ def transformStat(tree: Tree, index: Int): List[Tree] = tree match { case ModuleDef(mods, name, impl) => val sym = tree.symbol val cdef = ClassDef(mods | MODULE, name, List(), impl) .setPos(tree.pos) .setSymbol(sym.moduleClass) .setType(NoType); if (sym.isStatic) { if (!sym.allOverriddenSymbols.isEmpty) { val factory = sym.owner.newMethod(sym.pos, sym.name) .setFlag(sym.flags | STABLE).resetFlag(MODULE) .setInfo(PolyType(List(), sym.moduleClass.tpe)) sym.owner.info.decls.enter(factory) val ddef = atPhase(phase.next) { localTyper.typed { gen.mkModuleAccessDef(factory, sym.tpe) } } transformTrees(List(cdef, ddef)) } else { List(transform(cdef)) } } else { val vdef = localTyper.typed { atPos(tree.pos) { gen.mkModuleVarDef(sym) } } val ddef = atPhase(phase.next) { localTyper.typed { if (sym.owner.isTrait) gen.mkModuleAccessDcl(sym) else gen.mkCachedModuleAccessDef(sym, vdef.symbol) } } if (sym.owner.isTrait) transformTrees(List(cdef, ddef)) else transformTrees(List(cdef, vdef, ddef)) } case ValDef(_, _, _, _) => val tree1 = transform(tree); // important to do before forward reference check val ValDef(_, _, _, rhs) = tree1 if (tree.symbol.hasFlag(LAZY)) { assert(tree.symbol.isTerm, tree.symbol) val vsym = tree.symbol val hasUnitType = (tree.symbol.tpe.typeSymbol == definitions.UnitClass) val lazyDefSym = vsym.lazyAccessor assert(lazyDefSym != NoSymbol, vsym) val ownerTransformer = new ChangeOwnerTraverser(vsym, lazyDefSym) val lazyDef = atPos(tree.pos)( DefDef(lazyDefSym, vparamss => ownerTransformer( if (tree.symbol.owner.isTrait // for traits, this is further tranformed in mixins || hasUnitType) rhs else Block(List( Assign(gen.mkAttributedRef(vsym), rhs)), gen.mkAttributedRef(vsym))))) log("Made lazy def: " + lazyDef) if (hasUnitType) typed(lazyDef) :: Nil else typed(ValDef(vsym, EmptyTree)) :: typed(lazyDef) :: Nil } else { if (tree.symbol.isLocal && index <= currentLevel.maxindex && !tree.symbol.hasFlag(LAZY)) { if (settings.debug.value) Console.println(currentLevel.refsym); unit.error(currentLevel.refpos, "forward reference extends over definition of " + tree.symbol); } List(tree1) } case Import(_, _) => List() case _ => List(transform(tree)) } override def transform(tree: Tree): Tree = try { /* Check whether argument types conform to bounds of type parameters */ def checkBounds(pre: Type, owner: Symbol, tparams: List[Symbol], argtps: List[Type]): Unit = try { typer.infer.checkBounds(tree.pos, pre, owner, tparams, argtps, ""); } catch { case ex: TypeError => unit.error(tree.pos, ex.getMessage()); } def isIrrefutable(pat: Tree, seltpe: Type): Boolean = { val result = pat match { case Apply(_, args) => val clazz = pat.tpe.typeSymbol; clazz == seltpe.typeSymbol && clazz.isClass && (clazz hasFlag CASE) && List.forall2( args, clazz.primaryConstructor.tpe.asSeenFrom(seltpe, clazz).paramTypes)(isIrrefutable) case Typed(pat, tpt) => seltpe <:< tpt.tpe case Ident(nme.WILDCARD) => true case Bind(_, pat) => isIrrefutable(pat, seltpe) case _ => false } //Console.println("is irefutable? " + pat + ":" + pat.tpe + " against " + seltpe + ": " + result);//DEBUG result } /** If symbol is deprecated and is not contained in a depreceated definition, * issue a deprecated warning */ def checkDeprecated(sym: Symbol, pos: Position) { if (sym.isDeprecated && !currentOwner.ownerChain.exists(_.isDeprecated)) { unit.deprecationWarning(pos, sym+sym.locationString+" is deprecated") } } /** Check that a deprecated val or def does not override a * concrete, non-deprecated method. If it does, then * deprecation is meaningless. */ def checkDeprecatedOvers() { val symbol = tree.symbol if (symbol.isDeprecated) { val concrOvers = symbol.allOverriddenSymbols.filter(sym => !sym.isDeprecated && !sym.isDeferred) if(!concrOvers.isEmpty) unit.deprecationWarning( tree.pos, symbol.toString + " overrides concrete, non-deprecated symbol(s):" + concrOvers.map(_.fullNameString).mkString(" ", ", ", "")) } } def isRepeatedParamArg(tree: Tree) = currentApplication match { case Apply(fn, args) => !args.isEmpty && (args.last eq tree) && fn.tpe.paramTypes.length == args.length && fn.tpe.paramTypes.last.typeSymbol == RepeatedParamClass case _ => false } val savedLocalTyper = localTyper val savedCurrentApplication = currentApplication val sym = tree.symbol var result = tree tree match { case DefDef(mods, name, tparams, vparams, tpt, EmptyTree) if tree.symbol.hasAttribute(definitions.NativeAttr) => tree.symbol.resetFlag(DEFERRED) result = transform(copy.DefDef(tree, mods, name, tparams, vparams, tpt, typed(Apply(gen.mkAttributedRef(definitions.Predef_error), List(Literal("native method stub")))))) case DefDef(_, _, _, _, _, _) => checkDeprecatedOvers() case ValDef(_, _, _, _) => checkDeprecatedOvers() case Template(_, _, _) => localTyper = localTyper.atOwner(tree, currentOwner) validateBaseTypes(currentOwner) checkAllOverrides(currentOwner) case TypeTree() => new TypeTraverser { def traverse(tp: Type): TypeTraverser = tp match { case TypeRef(pre, sym, args) => checkDeprecated(sym, tree.pos) if (!tp.isHigherKinded) checkBounds(pre, sym.owner, sym.typeParams, args) this case _ => this } } traverse tree.tpe case TypeApply(fn, args) => checkBounds(NoPrefix, NoSymbol, fn.tpe.typeParams, args map (_.tpe)) if (sym.isSourceMethod && sym.hasFlag(CASE)) result = toConstructor(tree.pos, tree.tpe) case Apply( Select(qual, nme.filter), List(Function( List(ValDef(_, pname, tpt, _)), Match(_, CaseDef(pat1, _, _) :: _)))) if ((pname startsWith nme.CHECK_IF_REFUTABLE_STRING) && isIrrefutable(pat1, tpt.tpe)) => result = qual case Apply(fn, args) => checkSensible(tree.pos, fn, args) currentApplication = tree case If(cond, thenpart, elsepart) => cond.tpe match { case ConstantType(value) => result = if (value.booleanValue) thenpart else elsepart; if (result == EmptyTree) result = Literal(()).setPos(tree.pos).setType(UnitClass.tpe) case _ => } case New(tpt) => enterReference(tree.pos, tpt.tpe.typeSymbol) case Typed(expr, tpt @ Ident(name)) if (name == nme.WILDCARD_STAR.toTypeName) => if (!isRepeatedParamArg(tree)) unit.error(tree.pos, "no `: _*' annotation allowed here\n"+ "(such annotations are only allowed in arguments to *-parameters)") case Ident(name) => if (sym.isSourceMethod && sym.hasFlag(CASE)) result = toConstructor(tree.pos, tree.tpe) else if (name != nme.WILDCARD && name != nme.WILDCARD_STAR.toTypeName) { assert(sym != NoSymbol, tree)//debug enterReference(tree.pos, sym) } case Select(qual, name) => checkDeprecated(sym, tree.pos) if (currentClass != sym.owner && (sym hasFlag LOCAL)) { var o = currentClass var hidden = false while (!hidden && o != sym.owner && o != sym.owner.moduleClass && !o.isPackage) { hidden = o.isTerm || o.isPrivateLocal o = o.owner } if (!hidden) escapedPrivateLocals += sym } if (sym.isSourceMethod && sym.hasFlag(CASE)) result = toConstructor(tree.pos, tree.tpe) else qual match { case Super(qualifier, mix) => val base = qual.symbol; //Console.println("super: " + tree + " in " + base);//DEBUG assert(!(base.isTrait && sym.isTerm && mix == nme.EMPTY.toTypeName)) // term should have been eliminated by super accessors case _ => } case _ => } result = super.transform(result) result match { case ClassDef(_, _, _, _) | TypeDef(_, _, _, _) => if (result.symbol.isLocal || result.symbol.owner.isPackageClass) varianceValidator.traverse(result) case _ => } localTyper = savedLocalTyper currentApplication = savedCurrentApplication result } catch { case ex: TypeError => if (settings.debug.value) ex.printStackTrace(); unit.error(tree.pos, ex.getMessage()) tree } }}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?