📄 attr.java
字号:
Type site = env.enclClass.sym.type; if (methName == names._super) site = site.supertype(); if (site.tag == CLASS) { if (site.outer().tag == CLASS) { if (tree.meth.tag == Tree.SELECT) { Tree qualifier = ((Select) tree.meth).selected; chk.checkRefType(qualifier.pos, attribExpr(qualifier, localEnv, site.outer())); } else if (methName == names._super) { rs.resolveImplicitThis(tree.meth.pos, localEnv, site); } } else if (tree.meth.tag == Tree.SELECT) { log.error(tree.meth.pos, "illegal.qual.not.icls", site.tsym.toJava()); } boolean selectSuperPrev = ((AttrContext) localEnv.info).selectSuper; ((AttrContext) localEnv.info).selectSuper = true; Symbol sym = rs.resolveConstructor(tree.meth.pos, localEnv, site, argtypes); ((AttrContext) localEnv.info).selectSuper = selectSuperPrev; TreeInfo.setSymbol(tree.meth, sym); List saved = methTemplateSupply.elems; Type mpt = newMethTemplate(argtypes); checkId(tree.meth, site, sym, env, MTH, mpt); methTemplateSupply.elems = saved; } } result = syms.voidType; } else { argtypes = attribArgs(tree.args, localEnv); List saved = methTemplateSupply.elems; Type mpt = newMethTemplate(argtypes); Type mtype = attribExpr(tree.meth, localEnv, mpt); methTemplateSupply.elems = saved; result = check(tree, mtype.restype(), VAL, pkind, pt); } } /** * Check that given application node appears as first statement * in a constructor call. * @param tree The application node * @param env The environment current at the application. */ boolean checkFirstConstructorStat(Apply tree, Env env) { MethodDef enclMethod = env.enclMethod; if (enclMethod != null && enclMethod.name == names.init) { Block body = (Block) enclMethod.body; if (((Tree) body.stats.head).tag == Tree.EXEC && ((Exec) body.stats.head).expr == tree) return true; } log.error(tree.pos, "call.must.be.first.stmt.in.ctor", TreeInfo.name(tree.meth).toJava()); return false; } /** * Optimization: To avoid allocating a new methodtype for every * attribution of an Apply node, we use a reservoir. */ ListBuffer methTemplateSupply = new ListBuffer(); /** * Obtain an otherwise unused method type with given argument types. * Take it from the reservoir if non-empty, or create a new one. */ Type newMethTemplate(List argtypes) { if (methTemplateSupply.elems == methTemplateSupply.last) methTemplateSupply.append( new MethodType(null, null, null, syms.methodClass)); MethodType mt = (Type.MethodType) methTemplateSupply.elems.head; methTemplateSupply.elems = methTemplateSupply.elems.tail; mt.argtypes = argtypes; return mt; } public void visitNewClass(NewClass tree) { Type owntype = syms.errType; ClassDef cdef = tree.def; Tree clazz = tree.clazz; Tree clazzid = clazz; Tree clazzid1 = clazzid; if (tree.encl != null) { Type encltype = chk.checkRefType(tree.encl.pos, attribExpr(tree.encl, env)); clazzid1 = make.at(clazz.pos).Select(make.Type(encltype), ((Ident) clazzid).name); clazz = clazzid1; } Type clazztype = chk.checkClassType(tree.clazz.pos, attribType(clazz, env)); chk.validate(clazz); if (tree.encl != null) { tree.clazz.type = clazztype; TreeInfo.setSymbol(clazzid, TreeInfo.symbol(clazzid1)); clazzid.type = ((Ident) clazzid).sym.type; if ((clazztype.tsym.flags() & STATIC) != 0 && !clazztype.isErroneous()) { log.error(tree.pos, "qualified.new.of.static.class", clazztype.tsym.toJava()); } } else if ((clazztype.tsym.flags() & INTERFACE) == 0 && clazztype.outer().tag == CLASS) { rs.resolveImplicitThis(tree.pos, env, clazztype); } List argtypes = attribArgs(tree.args, env); if (clazztype.tag == CLASS) { if (cdef == null && (clazztype.tsym.flags() & (ABSTRACT | INTERFACE)) != 0) { log.error(tree.pos, "abstract.cant.be.instantiated", clazztype.tsym.toJava()); } else if (cdef != null && (clazztype.tsym.flags() & INTERFACE) != 0) { if (argtypes.nonEmpty()) { log.error(tree.pos, "anon.class.impl.intf.no.args"); argtypes = Type.emptyList; } else if (tree.encl != null) { log.error(tree.pos, "anon.class.impl.intf.no.qual.for.new"); } } else { boolean selectSuperPrev = ((AttrContext) env.info).selectSuper; if (cdef != null) ((AttrContext) env.info).selectSuper = true; tree.constructor = rs.resolveConstructor(tree.pos, env, clazztype, argtypes); ((AttrContext) env.info).selectSuper = selectSuperPrev; } if (cdef != null) { if (Resolve.isStatic(env)) cdef.flags |= STATIC; if ((clazztype.tsym.flags() & INTERFACE) != 0) { cdef.implementing = List.make(clazz); } else { cdef.extending = clazz; } attribStat(cdef, env.dup(tree)); if (tree.encl != null) { tree.args = tree.args.prepend(makeNullCheck(tree.encl)); argtypes = argtypes.prepend(tree.encl.type); tree.encl = null; } clazztype = cdef.sym.type; tree.constructor = rs.resolveConstructor(tree.pos, env, clazztype, argtypes); } if (tree.constructor != null && tree.constructor.kind == MTH) { owntype = clazztype; } } result = check(tree, owntype, VAL, pkind, pt); } /** * Make an attributed null check tree. */ public Tree makeNullCheck(Tree arg) { Name name = TreeInfo.name(arg); if (name == names._this || name == names._super) return arg; int optag = Tree.NULLCHK; Unary tree = make.at(arg.pos).Unary(optag, arg); tree.operator = syms.nullcheck; tree.type = arg.type; return tree; } public void visitNewArray(NewArray tree) { Type owntype = syms.errType; Type elemtype; if (tree.elemtype != null) { elemtype = attribType(tree.elemtype, env); chk.validate(tree.elemtype); owntype = elemtype; for (List l = tree.dims; l.nonEmpty(); l = l.tail) { attribExpr((Tree) l.head, env, syms.intType); owntype = new ArrayType(owntype, syms.arrayClass); } } else { if (pt.tag == ARRAY) { elemtype = pt.elemtype(); } else { if (pt.tag != ERROR) { log.error(tree.pos, "illegal.initializer.for.type", pt.toJava()); } elemtype = syms.errType; } } if (tree.elems != null) { attribExprs(tree.elems, env, elemtype); owntype = new ArrayType(elemtype, syms.arrayClass); } result = check(tree, owntype, VAL, pkind, pt); } public void visitParens(Parens tree) { Type owntype = attribTree(tree.expr, env, pkind, pt); result = check(tree, owntype, pkind, pkind, pt); Symbol sym = TreeInfo.symbol(tree); if (isType(sym)) { log.error(tree.pos, "illegal.start.of.expr"); } } public void visitAssign(Assign tree) { Type owntype = attribTree(tree.lhs, env.dup(tree), VAR, pt); attribExpr(tree.rhs, env, owntype); result = check(tree, owntype, VAL, pkind, pt); } public void visitAssignop(Assignop tree) { List argtypes = List.make(attribTree(tree.lhs, env, VAR, Type.noType), attribExpr(tree.rhs, env)); Symbol operator = tree.operator = rs.resolveOperator(tree.pos, tree.tag - Tree.ASGOffset, env, argtypes); Type owntype = (Type) argtypes.head; if (operator.kind == MTH) { if (owntype.tag <= DOUBLE) chk.checkCastable(tree.rhs.pos, operator.type.restype(), owntype); else if (owntype.tag == CLASS) chk.checkType(tree.lhs.pos, owntype, syms.stringType); else chk.checkType(tree.rhs.pos, operator.type.restype(), owntype); } result = check(tree, owntype, VAL, pkind, pt); } public void visitUnary(Unary tree) { Type argtype = (Tree.PREINC <= tree.tag && tree.tag <= Tree.POSTDEC) ? attribTree(tree.arg, env, VAR, Type.noType) : chk.checkNonVoid(tree.arg.pos, attribExpr(tree.arg, env)); Symbol operator = tree.operator = rs.resolveUnaryOperator(tree.pos, tree.tag, env, argtype); Type owntype = syms.errType; if (operator.kind == MTH) { owntype = operator.type.restype(); int opc = ((OperatorSymbol) operator).opcode; if (argtype.constValue != null) { Type ctype = cfolder.fold1(opc, argtype); if (ctype != null) { owntype = cfolder.coerce(ctype, owntype); if (tree.arg.type.tsym == syms.stringType.tsym) { tree.arg.type = syms.stringType; } } } } result = check(tree, owntype, VAL, pkind, pt); } public void visitBinary(Binary tree) { Type left = chk.checkNonVoid(tree.lhs.pos, attribExpr(tree.lhs, env)); Type right = chk.checkNonVoid(tree.lhs.pos, attribExpr(tree.rhs, env)); Symbol operator = tree.operator = rs.resolveBinaryOperator(tree.pos, tree.tag, env, left, right); Type owntype = syms.errType; if (operator.kind == MTH) { owntype = operator.type.restype(); int opc = ((OperatorSymbol) operator).opcode; if (opc == ByteCodes.error) { log.error(tree.lhs.pos, "operator.cant.be.applied", treeinfo.operatorName(tree.tag).toJava(), left.toJava() + "," + right.toJava()); } if (left.constValue != null && right.constValue != null) { Type ctype = cfolder.fold2(opc, left, right); if (ctype != null) { owntype = cfolder.coerce(ctype, owntype); if (tree.lhs.type.tsym == syms.stringType.tsym) { tree.lhs.type = syms.stringType; } if (tree.rhs.type.tsym == syms.stringType.tsym) { tree.rhs.type = syms.stringType; } } } if (opc == ByteCodes.if_acmpeq || opc == ByteCodes.if_acmpne) { if (!left.isCastable(right.erasure()) && !right.isCastable(left.erasure())) { log.error(tree.pos, "incomparable.types", left.toJava(), right.toJava()); } else { chk.checkCompatible(tree.pos, left, right); } } } result = check(tree, owntype, VAL, pkind, pt); } public void visitTypeCast(TypeCast tree) { Type clazztype = attribType(tree.clazz, env); Type exprtype = attribExpr(tree.expr, env, Type.noType); Type owntype = chk.checkCastable(tree.expr.pos, exprtype, clazztype); if (exprtype.constValue != null) owntype = cfolder.coerce(exprtype, owntype); result = check(tree, owntype, VAL, pkind, pt); } public void visitTypeTest(TypeTest tree) { Type exprtype = attribExpr(tree.expr, env); Type clazztype = chk.checkClassOrArrayType(tree.clazz.pos, attribType(tree.clazz, env)); chk.checkCastable(tree.expr.pos, exprtype, clazztype); result = check(tree, syms.booleanType, VAL, pkind, pt); } public void visitIndexed(Indexed tree) { Type owntype = syms.errType; Type atype = attribExpr(tree.indexed, env); attribExpr(tree.index, env, syms.intType); if (atype.tag == ARRAY) owntype = atype.elemtype(); else if (atype.tag != ERROR) log.error(tree.pos, "array.req.but.found", atype.toJava()); result = check(tree, owntype, VAR, pkind, pt); } public void visitIdent(Ident tree) { Symbol sym; if (pt.tag == METHOD) { sym = rs.resolveMethod(tree.pos, env, tree.name, pt.argtypes()); } else if (tree.sym != null && tree.sym.kind != VAR) { sym = tree.sym; } else { sym = rs.resolveIdent(tree.pos, env, tree.name, pkind); } tree.sym = sym; Env symEnv = env; boolean noOuterThisPath = false; if (env.enclClass.sym.owner.kind != PCK && (sym.kind & (VAR | MTH | TYP)) != 0 && sym.owner.kind == TYP && tree.name != names._this && tree.name != names._super) { while (symEnv.outer != null && !sym.isMemberOf(symEnv.enclClass.sym)) { if ((symEnv.enclClass.sym.flags() & NOOUTERTHIS) != 0) noOuterThisPath = true; symEnv = symEnv.outer; } } if (sym.kind == VAR) { VarSymbol v = (VarSymbol) sym; checkInit(tree, env, v); if (v.owner.kind == MTH && v.owner != ((AttrContext) env.info).scope.owner) { if ((v.flags_field & FINAL) == 0) { log.error(tree.pos, "local.var.accessed.from.icls.needs.final", v.toJava()); } } if (pkind == VAR)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -