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