📄 classreader.java
字号:
signatureBuffer[sbp++] = c; continue; } } } /** Convert (implicit) signature to list of types * until `terminator' is encountered. */ List<Type> sigToTypes(char terminator) { List<Type> head = List.of(null); List<Type> tail = head; while (signature[sigp] != terminator) tail = tail.setTail(List.of(sigToType())); sigp++; return head.tail; } /** Convert signature to type parameters, where signature is a name. */ List<Type> sigToTypeParams(Name name) { return sigToTypeParams(name.table.names, name.index, name.len); } /** Convert signature to type parameters, where signature is a byte * array segment. */ List<Type> sigToTypeParams(byte[] sig, int offset, int len) { signature = sig; sigp = offset; siglimit = offset + len; return sigToTypeParams(); } /** Convert signature to type parameters, where signature is implicit. */ List<Type> sigToTypeParams() { List<Type> tvars = List.nil(); if (signature[sigp] == '<') { sigp++; int start = sigp; sigEnterPhase = true; while (signature[sigp] != '>') tvars = tvars.prepend(sigToTypeParam()); sigEnterPhase = false; sigp = start; while (signature[sigp] != '>') sigToTypeParam(); sigp++; } return tvars.reverse(); } /** Convert (implicit) signature to type parameter. */ Type sigToTypeParam() { int start = sigp; while (signature[sigp] != ':') sigp++; Name name = names.fromUtf(signature, start, sigp - start); TypeVar tvar; if (sigEnterPhase) { tvar = new TypeVar(name, currentOwner, syms.botType); typevars.enter(tvar.tsym); } else { tvar = (TypeVar)findTypeVar(name); } List<Type> bounds = List.nil(); Type st = null; if (signature[sigp] == ':' && signature[sigp+1] == ':') { sigp++; st = syms.objectType; } while (signature[sigp] == ':') { sigp++; bounds = bounds.prepend(sigToType()); } if (!sigEnterPhase) { types.setBounds(tvar, bounds.reverse(), st); } return tvar; } /** Find type variable with given name in `typevars' scope. */ Type findTypeVar(Name name) { Scope.Entry e = typevars.lookup(name); if (e.scope != null) { return e.sym.type; } else { if (readingClassAttr) { // While reading the class attribute, the supertypes // might refer to a type variable from an enclosing element // (method or class). // If the type variable is defined in the enclosing class, // we can actually find it in // currentOwner.owner.type.getTypeArguments() // However, until we have read the enclosing method attribute // we don't know for sure if this owner is correct. It could // be a method and there is no way to tell before reading the // enclosing method attribute. TypeVar t = new TypeVar(name, currentOwner, syms.botType); missingTypeVariables = missingTypeVariables.prepend(t); // System.err.println("Missing type var " + name); return t; } throw badClassFile("undecl.type.var", name); } }/************************************************************************ * Reading Attributes ***********************************************************************/ /** Report unrecognized attribute. */ void unrecognized(Name attrName) { if (checkClassFile) printCCF("ccf.unrecognized.attribute", attrName); } /** Read member attribute. */ void readMemberAttr(Symbol sym, Name attrName, int attrLen) { //- System.err.println(" z " + sym + ", " + attrName + ", " + attrLen); if (attrName == names.ConstantValue) { Object v = readPool(nextChar()); // Ignore ConstantValue attribute if field not final. if ((sym.flags() & FINAL) != 0) ((VarSymbol)sym).setData(v); } else if (attrName == names.Code) { if (readAllOfClassFile || saveParameterNames) ((MethodSymbol)sym).code = readCode(sym); else bp = bp + attrLen; } else if (attrName == names.Exceptions) { int nexceptions = nextChar(); List<Type> thrown = List.nil(); for (int j = 0; j < nexceptions; j++) thrown = thrown.prepend(readClassSymbol(nextChar()).type); if (sym.type.getThrownTypes().isEmpty()) sym.type.asMethodType().thrown = thrown.reverse(); } else if (attrName == names.Synthetic) { // bridge methods are visible when generics not enabled if (allowGenerics || (sym.flags_field & BRIDGE) == 0) sym.flags_field |= SYNTHETIC; } else if (attrName == names.Bridge) { sym.flags_field |= BRIDGE; if (!allowGenerics) sym.flags_field &= ~SYNTHETIC; } else if (attrName == names.Deprecated) { sym.flags_field |= DEPRECATED; } else if (attrName == names.Varargs) { if (allowVarargs) sym.flags_field |= VARARGS; } else if (attrName == names.Annotation) { if (allowAnnotations) sym.flags_field |= ANNOTATION; } else if (attrName == names.Enum) { sym.flags_field |= ENUM; } else if (allowGenerics && attrName == names.Signature) { List<Type> thrown = sym.type.getThrownTypes(); sym.type = readType(nextChar()); //- System.err.println(" # " + sym.type); if (sym.kind == MTH && sym.type.getThrownTypes().isEmpty()) sym.type.asMethodType().thrown = thrown; } else if (attrName == names.RuntimeVisibleAnnotations) { attachAnnotations(sym); } else if (attrName == names.RuntimeInvisibleAnnotations) { attachAnnotations(sym); } else if (attrName == names.RuntimeVisibleParameterAnnotations) { attachParameterAnnotations(sym); } else if (attrName == names.RuntimeInvisibleParameterAnnotations) { attachParameterAnnotations(sym); } else if (attrName == names.LocalVariableTable) { int newbp = bp + attrLen; if (saveParameterNames) { // pick up parameter names from the variable table List<Name> parameterNames = List.nil(); int firstParam = ((sym.flags() & STATIC) == 0) ? 1 : 0; int endParam = firstParam + Code.width(sym.type.getParameterTypes()); int numEntries = nextChar(); for (int i=0; i<numEntries; i++) { int start_pc = nextChar(); int length = nextChar(); int nameIndex = nextChar(); int sigIndex = nextChar(); int register = nextChar(); if (start_pc == 0 && firstParam <= register && register < endParam) { int index = firstParam; for (Type t : sym.type.getParameterTypes()) { if (index == register) { parameterNames = parameterNames.prepend(readName(nameIndex)); break; } index += Code.width(t); } } } parameterNames = parameterNames.reverse(); ((MethodSymbol)sym).savedParameterNames = parameterNames; } bp = newbp; } else if (attrName == names.AnnotationDefault) { attachAnnotationDefault(sym); } else if (attrName == names.EnclosingMethod) { int newbp = bp + attrLen; readEnclosingMethodAttr(sym); bp = newbp; } else { unrecognized(attrName); bp = bp + attrLen; } } void readEnclosingMethodAttr(Symbol sym) { // sym is a nested class with an "Enclosing Method" attribute // remove sym from it's current owners scope and place it in // the scope specified by the attribute sym.owner.members().remove(sym); ClassSymbol self = (ClassSymbol)sym; ClassSymbol c = readClassSymbol(nextChar()); NameAndType nt = (NameAndType)readPool(nextChar()); MethodSymbol m = findMethod(nt, c.members_field, self.flags()); if (nt != null && m == null) throw badClassFile("bad.enclosing.method", self); self.name = simpleBinaryName(self.flatname, c.flatname) ; self.owner = m != null ? m : c; if (self.name.len == 0) self.fullname = null; else self.fullname = ClassSymbol.formFullName(self.name, self.owner); if (m != null) { ((ClassType)sym.type).setEnclosingType(m.type); } else if ((self.flags_field & STATIC) == 0) { ((ClassType)sym.type).setEnclosingType(c.type); } else { ((ClassType)sym.type).setEnclosingType(Type.noType); } enterTypevars(self); if (!missingTypeVariables.isEmpty()) { ListBuffer<Type> typeVars = new ListBuffer<Type>(); for (Type typevar : missingTypeVariables) { typeVars.append(findTypeVar(typevar.tsym.name)); } foundTypeVariables = typeVars.toList(); } else { foundTypeVariables = List.nil(); } } // See java.lang.Class private Name simpleBinaryName(Name self, Name enclosing) { String simpleBinaryName = self.toString().substring(enclosing.toString().length()); if (simpleBinaryName.length() < 1 || simpleBinaryName.charAt(0) != '$') throw badClassFile("bad.enclosing.method", self); int index = 1; while (index < simpleBinaryName.length() && isAsciiDigit(simpleBinaryName.charAt(index))) index++; return names.fromString(simpleBinaryName.substring(index)); } private MethodSymbol findMethod(NameAndType nt, Scope scope, long flags) { if (nt == null) return null; MethodType type = nt.type.asMethodType(); for (Scope.Entry e = scope.lookup(nt.name); e.scope != null; e = e.next()) if (e.sym.kind == MTH && isSameBinaryType(e.sym.type.asMethodType(), type)) return (MethodSymbol)e.sym; if (nt.name != names.init) // not a constructor return null; if ((flags & INTERFACE) != 0) // no enclosing instance return null; if (nt.type.getParameterTypes().isEmpty()) // no parameters return null; // A constructor of an inner class. // Remove the first argument (the enclosing instance) nt.type = new MethodType(nt.type.getParameterTypes().tail, nt.type.getReturnType(), nt.type.getThrownTypes(), syms.methodClass); // Try searching again return findMethod(nt, scope, flags); } /** Similar to Types.isSameType but avoids completion */ private boolean isSameBinaryType(MethodType mt1, MethodType mt2) { List<Type> types1 = types.erasure(mt1.getParameterTypes()) .prepend(types.erasure(mt1.getReturnType())); List<Type> types2 = mt2.getParameterTypes().prepend(mt2.getReturnType()); while (!types1.isEmpty() && !types2.isEmpty()) { if (types1.head.tsym != types2.head.tsym) return false; types1 = types1.tail; types2 = types2.tail; } return types1.isEmpty() && types2.isEmpty(); } /** * Character.isDigit answers <tt>true</tt> to some non-ascii * digits. This one does not. <b>copied from java.lang.Class</b> */ private static boolean isAsciiDigit(char c) { return '0' <= c && c <= '9'; } /** Read member attributes. */ void readMemberAttrs(Symbol sym) { char ac = nextChar(); for (int i = 0; i < ac; i++) { Name attrName = readName(nextChar()); int attrLen = nextInt(); readMemberAttr(sym, attrName, attrLen); } } /** Read class attribute. */ void readClassAttr(ClassSymbol c, Name attrName, int attrLen) { if (attrName == names.SourceFile) { Name n = readName(nextChar()); c.sourcefile = new SourceFileObject(n); } else if (attrName == names.InnerClasses) { readInnerClasses(c); } else if (allowGenerics && attrName == names.Signature) { readingClassAttr = true; try { ClassType ct1 = (ClassType)c.type; assert c == currentOwner; ct1.typarams_field = readTypeParams(nextChar()); ct1.supertype_field = sigToType(); ListBuffer<Type> is = new ListBuffer<Type>(); while (sigp != siglimit) is.append(sigToType()); ct1.interfaces_field = is.toList(); } finally { readingClassAttr = false; } } else { readMemberAttr(c, attrName, attrLen); } } private boolean readingClassAttr = false; private List<Type> missingTypeVariables = List.nil(); private List<Type> foundTypeVariables = List.nil(); /** Read class attributes.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -