classfileparser.scala

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

SCALA
821
字号
      getScope(jflags).enter(sym)    }  }  def parseMethod() {    val jflags = in.nextChar    var sflags = transFlags(jflags)    if ((jflags & JAVA_ACC_PRIVATE) != 0 && !global.settings.XO.value) {      val name = pool.getName(in.nextChar)      if (name == nme.CONSTRUCTOR)        sawPrivateConstructor = true      in.skip(2); skipAttributes()    } else {      if ((jflags & JAVA_ACC_BRIDGE) != 0) sflags = sflags | BRIDGE //PRIVATE      if ((sflags & PRIVATE) != 0 && global.settings.XO.value) {        in.skip(4); skipAttributes()      } else {        val name = pool.getName(in.nextChar)        var info = pool.getType(in.nextChar)        if (name == nme.CONSTRUCTOR)          info match {            case MethodType(formals, restpe) =>              assert(restpe.typeSymbol == definitions.UnitClass)              info = MethodType(formals, clazz.tpe)          }        val sym = getOwner(jflags)          .newMethod(NoPosition, name).setFlag(sflags).setInfo(info)        setPrivateWithin(sym, jflags)        parseAttributes(sym, info)        getScope(jflags).enter(sym)      }    }  }  private def sigToType(sym: Symbol, sig: Name): Type = {    var index = 0    val end = sig.length    val newTParams = new ListBuffer[Symbol]()    def accept(ch: Char) {      assert(sig(index) == ch)      index += 1    }    def objToAny(tp: Type): Type =      if (!global.phase.erasedTypes && tp.typeSymbol == definitions.ObjectClass)        definitions.AnyClass.tpe      else tp    def subName(isDelimiter: Char => Boolean): Name = {      val start = index      while (!isDelimiter(sig(index))) { index += 1 }      sig.subName(start, index)    }    def sig2type(tparams: Map[Name,Symbol]): Type = {      val tag = sig(index); index += 1      tag match {        case BYTE_TAG   => definitions.ByteClass.tpe        case CHAR_TAG   => definitions.CharClass.tpe        case DOUBLE_TAG => definitions.DoubleClass.tpe        case FLOAT_TAG  => definitions.FloatClass.tpe        case INT_TAG    => definitions.IntClass.tpe        case LONG_TAG   => definitions.LongClass.tpe        case SHORT_TAG  => definitions.ShortClass.tpe        case VOID_TAG   => definitions.UnitClass.tpe        case BOOL_TAG   => definitions.BooleanClass.tpe        case 'L' =>          def processClassType(tp: Type): Type = {            val classSym = tp.typeSymbol            val existentials = new ListBuffer[Symbol]()            if (sig(index) == '<') {              accept('<')              val xs = new ListBuffer[Type]()              var i = 0              while (sig(index) != '>') {                sig(index) match {                  case variance @ ('+' | '-' | '*') =>                    index += 1                    val bounds = variance match {                      case '+' => mkTypeBounds(definitions.AllClass.tpe,                                               sig2type(tparams))                      case '-' => mkTypeBounds(sig2type(tparams),                                               definitions.AnyClass.tpe)                      case '*' => mkTypeBounds(definitions.AllClass.tpe,                                               definitions.AnyClass.tpe)                    }                    val newtparam = makeExistential("?"+i, sym, bounds)                    existentials += newtparam                    xs += newtparam.tpe                    i += 1                  case _ =>                     xs += sig2type(tparams)                }              }               accept('>')              assert(xs.length > 0)              existentialAbstraction(existentials.toList,                                     appliedType(tp, xs.toList))            } else if (classSym.isMonomorphicType) {              tp            } else {              // raw type - existentially quantify all type parameters              val eparams = typeParamsToExistentials(classSym, classSym.unsafeTypeParams)                          val t = appliedType(classSym.typeConstructor, eparams.map(_.tpe))              val res = existentialAbstraction(eparams, t)              if (settings.debug.value && settings.verbose.value) println("raw type " + classSym + " -> " + res)              res            }          }          val classSym = classNameToSymbol(subName(c => c == ';' || c == '<'))          assert(!classSym.hasFlag(OVERLOADED), classSym.alternatives)          var tpe = processClassType(classSym.tpe)          while (sig(index) == '.') {            accept('.')            val name = subName(c => c == ';' || c == '.').toTypeName            val clazz = tpe.member(name)            assert(clazz.isAliasType, tpe)            tpe = processClassType(clazz.tpe)          }          accept(';')          tpe        case ARRAY_TAG =>          while ('0' <= sig(index) && sig(index) <= '9') index += 1          appliedType(definitions.ArrayClass.tpe, List(sig2type(tparams)))        case '(' =>          val paramtypes = new ListBuffer[Type]()          while (sig(index) != ')') {            paramtypes += objToAny(sig2type(tparams))          }          index += 1          val restype = if (sym != null && sym.isConstructor) {            accept('V')            clazz.tpe          } else            sig2type(tparams)          JavaMethodType(paramtypes.toList, restype)        case 'T' =>          val n = subName(';'.==).toTypeName          index += 1          tparams(n).typeConstructor      }    } // sig2type    var tparams = classTParams    if (sig(index) == '<') {      assert(sym != null)      index += 1      while (sig(index) != '>') {        val tpname = subName(':'.==).toTypeName        val s = sym.newTypeParameter(NoPosition, tpname)        tparams = tparams + (tpname -> s)        val ts = new ListBuffer[Type]        while (sig(index) == ':') {          index += 1          if (sig(index) != ':') // guard against empty class bound            ts += objToAny(sig2type(tparams))        }        s.setInfo(mkTypeBounds(definitions.AllClass.tpe,                               intersectionType(ts.toList, sym)))        newTParams += s      }      accept('>')    }    val tpe =      if ((sym eq null) || !sym.isClass)        sig2type(tparams)      else {        classTParams = tparams        val parents = new ListBuffer[Type]()        while (index < end) {          parents += sig2type(tparams)  // here the variance doesnt'matter        }        ClassInfoType(parents.toList, instanceDefs, sym)      }    polyType(newTParams.toList, tpe)  } // polySigToType  def parseAttributes(sym: Symbol, symtype: Type) {    def convertTo(c: Constant, pt: Type): Constant = {      if (pt.typeSymbol == definitions.BooleanClass && c.tag == IntTag)        Constant(c.value != 0)      else        c convertTo pt    }    def parseAttribute() {      val attrName = pool.getName(in.nextChar)      val attrLen = in.nextInt      val oldpb = in.bp      attrName match {        case nme.SignatureATTR =>          if (global.settings.target.value == "jvm-1.5") {            val sig = pool.getExternalName(in.nextChar)            val newType = sigToType(sym, sig)            sym.setInfo(newType)            if (settings.debug.value)              println("" + sym + "; signature = " + sig + " type = " + newType)            hasMeta = true          } else            in.skip(attrLen)        case nme.SyntheticATTR =>          sym.setFlag(SYNTHETIC)          in.skip(attrLen)        case nme.BridgeATTR =>          sym.setFlag(BRIDGE)          in.skip(attrLen)        case nme.DeprecatedATTR =>          sym.setFlag(DEPRECATED)          in.skip(attrLen)        case nme.ConstantValueATTR =>          val c = pool.getConstant(in.nextChar)          val c1 = convertTo(c, symtype)          if (c1 ne null) sym.setInfo(mkConstantType(c1))          else println("failure to convert " + c + " to " + symtype); //debug        case nme.InnerClassesATTR =>          if (!isScala) parseInnerClasses() else in.skip(attrLen)        case nme.ScalaSignatureATTR =>          unpickler.unpickle(in.buf, in.bp, clazz, staticModule, in.file.toString())          in.skip(attrLen)          this.isScala = true        case nme.JacoMetaATTR =>          val meta = pool.getName(in.nextChar).toString().trim()          metaParser.parse(meta, sym, symtype)          this.hasMeta = true        case nme.SourceFileATTR =>          assert(attrLen == 2)          val source = pool.getName(in.nextChar)          if (sourcePath ne null) {            val sourceFile0 = sourcePath.lookupPath(source.toString(), false)            if ((sourceFile0 ne null) && (clazz.sourceFile eq null)) {              clazz.sourceFile = sourceFile0            }            if (!inIDE || staticModule.moduleClass != NoSymbol)               staticModule.moduleClass.sourceFile = clazz.sourceFile          }        case nme.AnnotationDefaultATTR =>          sym.attributes =            AnnotationInfo(definitions.AnnotationDefaultAttr.tpe, List(), List()) :: sym.attributes          in.skip(attrLen)        case nme.RuntimeAnnotationATTR =>          parseAnnotations(attrLen)          if (settings.debug.value)            global.inform("" + sym + "; attributes = " + sym.attributes)        case _ =>          in.skip(attrLen)      }    }    def parseTaggedConstant: Constant = {      val tag = in.nextByte      val index = in.nextChar      tag match {        case STRING_TAG => Constant(pool.getName(index).toString())        case BOOL_TAG   => pool.getConstant(index)        case BYTE_TAG   => pool.getConstant(index)        case CHAR_TAG   => pool.getConstant(index)        case SHORT_TAG  => pool.getConstant(index)        case INT_TAG    => pool.getConstant(index)        case LONG_TAG   => pool.getConstant(index)        case FLOAT_TAG  => pool.getConstant(index)        case DOUBLE_TAG => pool.getConstant(index)        case CLASS_TAG  => Constant(pool.getType(index))        case ENUM_TAG   =>          val t = pool.getType(index)          val n = pool.getName(in.nextChar)          val s = t.typeSymbol.linkedModuleOfClass.info.decls.lookup(n)          //assert (s != NoSymbol, "while processing " + in.file + ": " + t + "." + n + ": " + t.decls)          assert(s != NoSymbol, t) // avoid string concatenation!          Constant(s)        case ARRAY_TAG  =>          val arr = new ArrayBuffer[Constant]()          for (i <- 0 until index) {            arr += parseTaggedConstant          }          new ArrayConstant(arr.toArray,              appliedType(definitions.ArrayClass.typeConstructor, List(arr(0).tpe)))	case ANNOTATION_TAG =>	  parseAnnotation(index)  // skip it	  new AnnotationConstant()      }    }    /** Parse and return a single annotation.  If it is malformed,     *  throw an exception.  If it contains a nested annotation,     *  return None.     */    def parseAnnotation(attrNameIndex: Char): Option[AnnotationInfo] = {      val attrType = pool.getType(attrNameIndex)      val nargs = in.nextChar      val nvpairs = new ListBuffer[(Name,AnnotationArgument)]      var nestedAnnot = false  // if a nested annotation is seen,                               // then skip this annotation      for (i <- 0 until nargs) {        val name = pool.getName(in.nextChar)	val argConst = parseTaggedConstant	if (argConst.tag == AnnotationTag)	  nestedAnnot = true	else          nvpairs += ((name, new AnnotationArgument(argConst)))      }      if (nestedAnnot)	None      else	Some(AnnotationInfo(attrType, List(), nvpairs.toList))    }    /** Parse a sequence of annotations and attach them to the     *  current symbol sym.     */    def parseAnnotations(len: Int) {      val nAttr = in.nextChar      for (n <- 0 until nAttr)	parseAnnotation(in.nextChar) match {	  case None =>	    if (settings.debug.value)              global.inform("dropping annotation on " +			    sym +			    " that has a nested annotation")	  case Some(annot) =>            sym.attributes = annot :: sym.attributes	}    }    def makeInnerAlias(outer: Symbol, name: Name, iclazz: Symbol, scope: Scope): Symbol = {      var innerAlias = scope.lookup(name)      if (!innerAlias.isAliasType) {        innerAlias = outer.newAliasType(NoPosition, name).setFlag(JAVA)          .setInfo(new LazyAliasType(iclazz))        scope.enter(innerAlias)      }      innerAlias    }    def parseInnerClasses() {      for (i <- 0 until in.nextChar) {        val innerIndex = in.nextChar        val outerIndex = in.nextChar        val nameIndex = in.nextChar        val jflags = in.nextChar        if (innerIndex != 0 && outerIndex != 0 && nameIndex != 0 &&             pool.getClassSymbol(outerIndex) == sym) {          makeInnerAlias(            getOwner(jflags),             pool.getName(nameIndex).toTypeName,             pool.getClassSymbol(innerIndex),            getScope(jflags))                    if ((jflags & JAVA_ACC_STATIC) != 0) {            val innerVal = staticModule.newValue(NoPosition, pool.getName(nameIndex).toTermName)              .setInfo(pool.getClassSymbol(innerIndex).linkedModuleOfClass.moduleClass.thisType)            staticDefs.enter(innerVal)          }        }      }    }    val attrCount = in.nextChar    for (i <- 0 until attrCount) parseAttribute()  }  class LazyAliasType(alias: Symbol) extends LazyType {    override def complete(sym: Symbol) {      alias.initialize      val tparams1 = cloneSymbols(alias.typeParams)      sym.setInfo(polyType(tparams1, alias.tpe.substSym(alias.typeParams, tparams1)))    }  }  def skipAttributes() {    val attrCount = in.nextChar    for (i <- 0 until attrCount) {      in.skip(2); in.skip(in.nextInt)    }  }  def skipMembers() {    val memberCount = in.nextChar    for (i <- 0 until memberCount) {      in.skip(6); skipAttributes()    }  }  protected def getOwner(flags: Int): Symbol =    if ((flags & JAVA_ACC_STATIC) != 0) statics else clazz  protected def getScope(flags: Int): Scope =    if ((flags & JAVA_ACC_STATIC) != 0) staticDefs else instanceDefs  protected def transFlags(flags: Int): Long = {    var res = 0l    if ((flags & JAVA_ACC_PRIVATE) != 0)      res = res | PRIVATE    else if ((flags & JAVA_ACC_PROTECTED) != 0)      res = res | PROTECTED    if ((flags & JAVA_ACC_ABSTRACT) != 0 && (flags & JAVA_ACC_ANNOTATION) == 0)      res = res | DEFERRED    if ((flags & JAVA_ACC_FINAL) != 0)      res = res | FINAL    if (((flags & JAVA_ACC_INTERFACE) != 0) &&        ((flags & JAVA_ACC_ANNOTATION) == 0))      res = res | TRAIT | INTERFACE | ABSTRACT    if ((flags & JAVA_ACC_SYNTHETIC) != 0)      res = res | SYNTHETIC    if ((flags & JAVA_ACC_STATIC) != 0)      res = res | STATIC    res | JAVA  }  private def setPrivateWithin(sym: Symbol, jflags: Int) {    if ((jflags & (JAVA_ACC_PRIVATE | JAVA_ACC_PROTECTED | JAVA_ACC_PUBLIC)) == 0)      sym.privateWithin = sym.toplevelClass.owner  }}

⌨️ 快捷键说明

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