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