📄 transinner.java
字号:
throw new AssertionError(); } } /** * The name of the access method with number `anum' and access code `acode'. */ Name accessName(int anum, int acode) { return names.fromString("access$" + anum + acode / 10 + acode % 10); } /** * Return access symbol for a private or protected symbol from an inner class. * @param sym The accessed private symbol. * @param tree The accessing tree. * @param enclOp The closest enclosing operation node of tree, * null if tree is not a subtree of an operation. * @param protAccess Is access to a protected symbol in another * package? * @param refSuper Is access via a (qualified) C.super? */ MethodSymbol accessSymbol(Symbol sym, Tree tree, Tree enclOp, boolean protAccess, boolean refSuper) { ClassSymbol accOwner = refSuper && protAccess ? (ClassSymbol)((Select) tree).selected.type.tsym : accessClass(sym, protAccess); Symbol vsym = sym; if (sym.owner != accOwner) { vsym = sym.clone(accOwner); actualSymbols.put(vsym, sym); } Integer anum = (Integer) accessNums.get(vsym); if (anum == null) { anum = new Integer(accessed.length()); accessNums.put(vsym, anum); accessSyms.put(vsym, new MethodSymbol[NCODES]); accessed.append(vsym); } int acode; List argtypes; Type restype; List thrown; switch (vsym.kind) { case VAR: acode = accessCode(tree, enclOp); if (acode >= FIRSTASGOPcode) { OperatorSymbol operator = binaryAccessOperator(acode); if (operator.opcode == string_add) argtypes = List.make(syms.objectType); else argtypes = operator.type.argtypes().tail; } else if (acode == ASSIGNcode) argtypes = Type.emptyList.prepend(vsym.erasure()); else argtypes = Type.emptyList; restype = vsym.erasure(); thrown = Type.emptyList; break; case MTH: acode = DEREFcode; argtypes = vsym.erasure().argtypes(); restype = vsym.erasure().restype(); thrown = vsym.type.thrown(); break; default: throw new AssertionError(); } if (protAccess && refSuper) acode++; if ((vsym.flags() & STATIC) == 0) { argtypes = argtypes.prepend(vsym.owner.erasure()); } MethodSymbol[] accessors = (Symbol.MethodSymbol[]) accessSyms.get(vsym); MethodSymbol accessor = accessors[acode]; if (accessor == null) { accessor = new MethodSymbol(STATIC | SYNTHETIC, accessName(anum.intValue(), acode), new MethodType(argtypes, restype, thrown, syms.methodClass), accOwner); enterSynthetic(tree.pos, accessor, accOwner.members()); accessors[acode] = accessor; } return accessor; } /** * The qualifier to be used for accessing a symbol in an outer class. * This is either C.sym or C.this.sym, depending on whether or not * sym is static. * @param sym The accessed symbol. */ Tree accessBase(int pos, Symbol sym) { return (sym.flags() & STATIC) != 0 ? access(make.at(pos).QualIdent(sym.owner)) : makeOwnerThis(pos, sym, true); } /** * Do we need an access method to reference private symbol? */ boolean needsPrivateAccess(Symbol sym) { if ((sym.flags() & PRIVATE) == 0 || sym.owner == currentClass) { return false; } else if (sym.name == names.init && (sym.owner.owner.kind & (VAR | MTH)) != 0) { sym.flags_field &= ~PRIVATE; return false; } else { return true; } } /** * Do we need an access method to reference symbol in other package? */ boolean needsProtectedAccess(Symbol sym) { return (sym.flags() & PROTECTED) != 0 && sym.owner.owner != currentClass.owner && sym.packge() != currentClass.packge() && !currentClass.isSubClass(sym.owner); } /** * The class in which an access method for given symbol goes. * @param sym The access symbol * @param protAccess Is access to a protected symbol in another * package? */ ClassSymbol accessClass(Symbol sym, boolean protAccess) { if (protAccess) { ClassSymbol c = currentClass; while (!c.isSubClass(sym.owner)) { c = c.owner.enclClass(); } return c; } else { return sym.owner.enclClass(); } } /** * Ensure that identifier is accessible, return tree accessing the identifier. * @param sym The accessed symbol. * @param tree The tree referring to the symbol. * @param enclOp The closest enclosing operation node of tree, * null if tree is not a subtree of an operation. * @param refSuper Is access via a (qualified) C.super? */ Tree access(Symbol sym, Tree tree, Tree enclOp, boolean refSuper) { while (sym.kind == VAR && sym.owner.kind == MTH && sym.owner.enclClass() != currentClass) { Object cv = ((VarSymbol) sym).constValue; if (cv != null) { make.at(tree.pos); return makeLit(sym.type, cv); } sym = proxies.lookup(proxyName(sym.name)).sym; assert sym != null && (sym.flags_field & FINAL) != 0; tree = make.at(tree.pos).Ident(sym); } Tree base = (tree.tag == Tree.SELECT) ? ((Select) tree).selected : null; switch (sym.kind) { case TYP: if (sym.owner.kind != PCK) { Name flatname = Convert.shortName(sym.flatName()); while (base != null && TreeInfo.symbol(base) != null && TreeInfo.symbol(base).kind != PCK) { base = (base.tag == Tree.SELECT) ? ((Select) base).selected : null; } if (tree.tag == Tree.IDENT) { ((Ident) tree).name = flatname; } else if (base == null) { tree = make.at(tree.pos).Ident(sym); ((Ident) tree).name = flatname; } else { ((Select) tree).selected = base; ((Select) tree).name = flatname; } } break; case MTH: case VAR: if (sym.owner.kind == TYP) { boolean protAccess = refSuper && !needsPrivateAccess(sym) || needsProtectedAccess(sym); boolean accReq = protAccess || needsPrivateAccess(sym); boolean baseReq = base == null && sym.owner != syms.predefClass && !sym.isMemberOf(currentClass); if (accReq || baseReq) { make.at(tree.pos); if (sym.kind == VAR) { Object cv = ((VarSymbol) sym).constValue; if (cv != null) return makeLit(sym.type, cv); } if (accReq) { List args = Tree.emptyList; if ((sym.flags() & STATIC) == 0) { if (base == null) base = makeOwnerThis(tree.pos, sym, true); args = args.prepend(base); base = null; } Symbol access = accessSymbol(sym, tree, enclOp, protAccess, refSuper); Tree receiver = make.Select(base != null ? base : make.QualIdent(access.owner), access); return make.App(receiver, args); } else if (baseReq) { return make.at(tree.pos).Select( accessBase(tree.pos, sym), sym); } } } } return tree; } /** * Ensure that identifier is accessible, return tree accessing the identifier. * @param tree The identifier tree. */ Tree access(Tree tree) { Symbol sym = TreeInfo.symbol(tree); return sym == null ? tree : access(sym, tree, null, false); } /** * Return access constructor for a private constructor, * or the constructor itself, if no access constructor is needed. * @param pos The position to report diagnostics, if any. * @param constr The private constructor. */ Symbol accessConstructor(int pos, Symbol constr) { if (needsPrivateAccess(constr)) { ClassSymbol accOwner = accessClass(constr, false); MethodSymbol aconstr = (Symbol.MethodSymbol) accessConstrs.get(constr); if (aconstr == null) { aconstr = new MethodSymbol(SYNTHETIC, names.init, new MethodType( constr.type.argtypes().append( accessConstructorTag().type), constr.type.restype(), constr.type.thrown(), syms.methodClass), accOwner); enterSynthetic(pos, aconstr, accOwner.members()); accessConstrs.put(constr, aconstr); accessed.append(constr); } return aconstr; } else { return constr; } } /** * Return an anonymous class nested in this toplevel class. */ ClassSymbol accessConstructorTag() { ClassSymbol topClass = currentClass.outermostClass(); Name flatname = names.fromString(topClass.fullName() + "$1"); ClassSymbol ctag = (Symbol.ClassSymbol) chk.compiled.get(flatname); if (ctag == null) ctag = makeEmptyClass(STATIC | SYNTHETIC, topClass); return ctag; } /** * Add all required access methods for a private symbol to enclosing class. * @param sym The symbol. */ void makeAccessible(Symbol sym) { ClassDef cdef = classDef(sym.owner.enclClass()); assert cdef != null : "class def not found: " + sym + " in " + sym.owner; if (sym.name == names.init) { cdef.defs = cdef.defs.prepend( accessConstructorDef(cdef.pos, sym, (Symbol.MethodSymbol) accessConstrs.get(sym))); } else { MethodSymbol[] accessors = (Symbol.MethodSymbol[]) accessSyms.get(sym); for (int i = 0; i < NCODES; i++) { if (accessors[i] != null) cdef.defs = cdef.defs.prepend( accessDef(cdef.pos, sym, accessors[i], i)); } } } /** * Construct definition of an access method. * @param pos The source code position of the definition. * @param sym The private or protected symbol. * @param accessor The access method for the symbol. * @param acode The access code. */ Tree accessDef(int pos, Symbol vsym, MethodSymbol accessor, int acode) { currentClass = vsym.owner.enclClass(); make.at(pos); MethodDef md = make.MethodDef(accessor, null); Symbol sym = (Symbol) actualSymbols.get(vsym); if (sym == null) sym = vsym; Tree ref; List args; if ((sym.flags() & STATIC) != 0) { ref = make.Ident(sym); args = make.Idents(md.params); } else { ref = make.Select(make.Ident((Tree.VarDef) md.params.head), sym); args = make.Idents(md.params.tail); } Tree stat; if (sym.kind == VAR) { int acode1 = acode - (acode & 1); Tree expr; switch (acode1) { case DEREFcode: expr = ref; break; case ASSIGNcode: expr = make.Assign(ref, (Tree) args.head); break; case PREINCcode: case POSTINCcode: case PREDECcode: case POSTDECcode: expr = makeUnary(((acode1 - PREINCcode)>> 1) + Tree.PREINC, ref); break; default: expr = make.Assignop(treeTag(binaryAccessOperator(acode1)), ref, (Tree) args.head); ((Assignop) expr).operator = binaryAccessOperator(acode1); } stat = make.Return(expr.setType(sym.type)); } else { stat = make.Call(make.App(ref, args)); } md.body = make.Block(0, List.make(stat)); for (List l = md.params; l.nonEmpty(); l = l.tail) ((Tree.VarDef) l.head).vartype = access(((Tree.VarDef) l.head).vartype); md.restype = access(md.restype); for (List l = md.thrown; l.nonEmpty(); l = l.tail) l.head = access((Tree) l.head); return md; } /**
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -