contexts.scala

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

SCALA
643
字号
          enterElems(c.outer)          enterLocalElems(c.scope.elems)        }      }      enterElems(this)      argContext    }    //todo: remove    def makeConstructorSuffixContext = {      val c = make(tree)      c.inConstructorSuffix = true      c    }    def error(pos: Position, err: Error) {      val msg = err.getMessage()      if (reportGeneralErrors)        unit.error(pos, if (checking) "**** ERROR DURING INTERNAL CHECKING ****\n" + msg else msg)      else        throw err    }    def error(pos: Position, msg: String) {      if (reportGeneralErrors)        unit.error(pos, if (checking) "**** ERROR DURING INTERNAL CHECKING ****\n" + msg else msg)      else        throw new TypeError(pos, msg)    }    def warning(pos:  Position, msg: String) {      if (reportGeneralErrors) unit.warning(pos, msg)    }    /**     *  @param pos  ...     *  @param pre  ...     *  @param sym1 ...     *  @param sym2 ...     *  @param rest ...     */    def ambiguousError(pos: Position, pre: Type, sym1: Symbol,                       sym2: Symbol, rest: String) {      val msg =        ("ambiguous reference to overloaded definition,\n" +         "both " + sym1 + sym1.locationString + " of type " + pre.memberType(sym1) +         "\nand  " + sym2 + sym2.locationString + " of type " + pre.memberType(sym2) +         "\nmatch " + rest)      if (reportAmbiguousErrors) {        if (!pre.isErroneous && !sym1.isErroneous && !sym2.isErroneous)          unit.error(pos, msg)      } else throw new TypeError(pos, msg)    }    def outerContext(clazz: Symbol): Context = {      var c = this      while (c != NoContext && c.owner != clazz) c = c.outer.enclClass      c    }    def isLocal(): Boolean = tree match {      case Block(_,_) => true      case PackageDef(_, _) => false      case EmptyTree => false      case _ => outer.isLocal()    }    def nextEnclosing(p: Context => Boolean): Context =      if (this == NoContext || p(this)) this else outer.nextEnclosing(p)    override def toString(): String = {      if (this == NoContext) "NoContext"      else owner.toString() + " @ " + tree.getClass() +           " " + tree.toString() + ", scope = " + scope.hashCode() +           " " + scope.toList + "\n:: " + outer.toString()    }    /** Return closest enclosing context that defines a superclass of `clazz', or a      *  companion module of a superclass of `clazz', or NoContext if none exists */    def enclosingSuperClassContext(clazz: Symbol): Context = {      var c = this.enclClass      while (c != NoContext &&              !clazz.isNonBottomSubClass(c.owner) &&             !(c.owner.isModuleClass && clazz.isNonBottomSubClass(c.owner.linkedClassOfModule)))        c = c.outer.enclClass      c    }    /** Return closest enclosing context that defines a subclass of `clazz', or NoContext     *  if none exists */    def enclosingSubClassContext(clazz: Symbol): Context = {      var c = this.enclClass      while (c != NoContext && !c.owner.isNonBottomSubClass(clazz))        c = c.outer.enclClass      c    }    /** Is <code>sym</code> accessible as a member of tree `site' with type     *  <code>pre</code> in current context?     *     *  @param sym         ...     *  @param pre         ...     *  @param superAccess ...     *  @return            ...     */    def isAccessible(sym: Symbol, pre: Type, superAccess: Boolean): Boolean = {      /** Are we inside definition of `owner'? */      def accessWithin(owner: Symbol): Boolean = {        var c = this        while (c != NoContext && c.owner != owner) {          if (false && inIDE) // XXX: we didn't get to update these syms....             assert(c.owner.fullNameString != owner.fullNameString)          if (c.outer eq null) assert(false, "accessWithin(" + owner + ") " + c);//debug          if (c.outer.enclClass eq null) assert(false, "accessWithin(" + owner + ") " + c);//debug          c = c.outer.enclClass        }        c != NoContext      }      /** Is `clazz' a subclass of an enclosing class? */      def isSubClassOfEnclosing(clazz: Symbol): Boolean =        enclosingSuperClassContext(clazz) != NoContext      def isSubThisType(pre: Type, clazz: Symbol): Boolean = pre match {        case ThisType(pclazz) => pclazz isNonBottomSubClass clazz        case _ => false      }      (pre == NoPrefix) || {        val ab = sym.accessBoundary(sym.owner)        ((ab.isTerm || ab == definitions.RootClass)         ||         (accessWithin(ab) || accessWithin(ab.linkedClassOfClass)) &&         (!sym.hasFlag(LOCAL) ||           (sym hasFlag PROTECTED) && isSubThisType(pre, sym.owner) ||          pre =:= sym.owner.thisType)         ||         (sym hasFlag PROTECTED) &&         (superAccess ||          (pre.widen.typeSymbol.isNonBottomSubClass(sym.owner) &&            (isSubClassOfEnclosing(pre.widen.typeSymbol) || phase.erasedTypes))))        // note: phase.erasedTypes disables last test, because fater addinterfaces        // implementation classes are not in the superclass chain. If we enable the        // test, bug780 fails.      }    }    def pushTypeBounds(sym: Symbol) {      savedTypeBounds = (sym, sym.info) :: savedTypeBounds    }    def restoreTypeBounds(tp: Type): Type = {      var current = tp      for ((sym, info) <- savedTypeBounds) {        if (settings.debug.value) log("resetting " + sym + " to " + info);        sym.info match {          case TypeBounds(lo, hi) if (hi <:< lo && lo <:< hi) =>             current = current.instantiateTypeParams(List(sym), List(lo))//@M TODO: when higher-kinded types are inferred, probably need a case PolyType(_, TypeBounds(...)) if ... =>                      case _ =>        }        sym.setInfo(info)      }      savedTypeBounds = List()      current    }    private var implicitsCache: List[List[ImplicitInfo]] = null    private var implicitsRunId = NoRunId        def resetCache : Unit = {      implicitsRunId = NoRunId      implicitsCache = null      if (outer != null && outer != this) outer.resetCache    }    private def collectImplicits(syms: List[Symbol], pre: Type): List[ImplicitInfo] =      for (sym <- syms if sym.hasFlag(IMPLICIT) && isAccessible(sym, pre, false))      yield new ImplicitInfo(sym.name, pre, sym)    private def collectImplicitImports(imp: ImportInfo): List[ImplicitInfo] = {      val pre = imp.qual.tpe      def collect(sels: List[(Name, Name)]): List[ImplicitInfo] = sels match {        case List() => List()        case List((nme.WILDCARD, _)) => collectImplicits(pre.implicitMembers, pre)        case (from, to) :: sels1 =>           var impls = collect(sels1) filter (info => info.name != from)          if (to != nme.WILDCARD) {            val sym = imp.importedSymbol(to)            if (sym.hasFlag(IMPLICIT)) impls = new ImplicitInfo(to, pre, sym) :: impls          }          impls      }      if (settings.debug.value)        log("collect implicit imports " + imp + "=" + collect(imp.tree.selectors))//debug      collect(imp.tree.selectors)    }    def implicitss: List[List[ImplicitInfo]] = {      val nextOuter =         if (owner.isConstructor) {          if (outer.tree.isInstanceOf[Template]) outer.outer.outer          else outer.outer        } else outer        // can we can do something smarter to bring back the implicit cache?      if (implicitsRunId != currentRunId) {        implicitsRunId = currentRunId        implicitsCache = List()        val newImplicits: List[ImplicitInfo] =          if (owner != nextOuter.owner && owner.isClass && !owner.isPackageClass) {            if (!owner.isInitialized) return nextOuter.implicitss            if (settings.debug.value)              log("collect member implicits " + owner + ", implicit members = " +                  owner.thisType.implicitMembers)//debug            collectImplicits(owner.thisType.implicitMembers, owner.thisType)          } else if (scope != nextOuter.scope && !owner.isPackageClass) {            if (settings.debug.value)              log("collect local implicits " + scope.toList)//debug            collectImplicits(scope.toList, NoPrefix)          } else if (imports != nextOuter.imports) {            assert(imports.tail == nextOuter.imports)            collectImplicitImports(imports.head)          } else List()        implicitsCache = if (newImplicits.isEmpty) nextOuter.implicitss                         else newImplicits :: nextOuter.implicitss      }      implicitsCache    }    override def hashCode = {      var hc = 0      implicit def b2i(b : Boolean) = if (b) 1 else 0      // assum enclClass/enclMethod/outer are all interned already.      hc += tree.hashCodeStructure      def f(txt : Context) = if (txt eq this) 0 else System.identityHashCode(txt)      hc += f(enclClass)      hc += f(enclMethod)      hc += f(outer)      hc += owner.hashCode      hc += scope.hashCode      hc += variance.hashCode      hc += _undetparams.hashCode      hc += depth      hc += imports.hashCode      hc += prefix.hashCode      hc += inConstructorSuffix      hc += checking      hc += retyping      hc += savedTypeBounds.hashCode      hc += (if (unit eq null) 0 else unit.hashCode)      hc    }      }  class ImportInfo(val tree: Import, val depth: Int) {    /** The prefix expression */    def qual: Tree = tree.symbol.info match {      case ImportType(expr) => expr      case _ => throw new FatalError("symbol " + tree.symbol + " has bad type: " + tree.symbol.info);//debug    }    /** Is name imported explicitly, not via wildcard? */    def isExplicitImport(name: Name): Boolean =      tree.selectors exists (_._2 == name.toTermName)    /** The symbol with name <code>name</code> imported from import clause     *  <code>tree</code>.     */    def importedSymbol(name: Name): Symbol = {      var result: Symbol = NoSymbol      var renamed = false      var selectors = tree.selectors      while (selectors != Nil && result == NoSymbol) {        if (selectors.head._1 != nme.WILDCARD)          notifyImport(name, qual.tpe, selectors.head._1, selectors.head._2)        if (selectors.head._2 == name.toTermName)          result = qual.tpe.member(            if (name.isTypeName) selectors.head._1.toTypeName else selectors.head._1)        else if (selectors.head._1 == name.toTermName)          renamed = true        else if (selectors.head._1 == nme.WILDCARD && !renamed)          result = qual.tpe.member(name)        selectors = selectors.tail      }      result    }    override def toString() = tree.toString()        override def hashCode = tree.hashCodeStructure + depth    override def equals(that : Any) = that match {      case that : ImportInfo =>        depth == that.depth && (tree equalsStructure that.tree)      case _ => false    }  }  class ImplicitInfo(val name: Name, val pre: Type, val sym: Symbol) {    private var tpeCache: Type = null    def tpe: Type = {      if (tpeCache eq null) tpeCache = pre.memberType(sym)      tpeCache    }    override def toString = "ImplicitInfo(" + name + "," + pre + "," + sym + ")"  }  val NoImplicitInfo = new ImplicitInfo(null, null, null)  case class ImportType(expr: Tree) extends Type {    override def equals(that : Any) = that match {    case ImportType(expr) =>      if (inIDE) this.expr equalsStructure expr      else this.expr == expr    case _ => false    }    override def hashCode = if (inIDE) expr.hashCodeStructure else expr.hashCode  }  protected def intern(txt : Context) = txt  }

⌨️ 快捷键说明

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