📄 attr.java
字号:
checkAssignable(tree.pos, v, null, env); } if ((((AttrContext) symEnv.info).isSelfCall || noOuterThisPath) && (sym.kind & (VAR | MTH)) != 0 && sym.owner.kind == TYP && (sym.flags() & STATIC) == 0) { chk.earlyRefError(tree.pos, sym.kind == VAR ? sym : thisSym(env)); } result = checkId(tree, env.enclClass.sym.type, sym, env, pkind, pt); } public void visitSelect(Select tree) { int skind = 0; if (tree.name == names._this || tree.name == names._super || tree.name == names._class) { skind = TYP; } else { if ((pkind & PCK) != 0) skind = skind | PCK; if ((pkind & TYP) != 0) skind = skind | TYP | PCK; if ((pkind & (VAL | MTH)) != 0) skind = skind | VAL | TYP; } Type site = attribTree(tree.selected, env, skind, Infer.anyPoly); Symbol sitesym = TreeInfo.symbol(tree.selected); boolean selectSuperPrev = ((AttrContext) env.info).selectSuper; ((AttrContext) env.info).selectSuper = sitesym != null && (sitesym.name == names._super || sitesym.kind == TYP); Symbol sym = selectSym(tree, site, env, pt, pkind); tree.sym = sym; if (sym.kind == VAR) { VarSymbol v = (VarSymbol) sym; evalInit(v); if (pkind == VAR) checkAssignable(tree.pos, v, tree.selected, env); } if (isType(sym) && (sitesym == null || (sitesym.kind & (TYP | PCK)) == 0)) { tree.type = check(tree.selected, pt, sitesym == null ? VAL : sitesym.kind, TYP | PCK, pt); } if (((AttrContext) env.info).selectSuper) { if ((sym.flags() & STATIC) == 0 && sym.name != names._this && sym.name != names._super) { if (sitesym.name == names._super) { rs.checkNonAbstract(tree.pos, sym); } else if (sym.kind == VAR || sym.kind == MTH) { rs.access(new Resolve.StaticError(sym), tree.pos, site, sym.name, true); } if (site.isRaw()) { Type site1 = env.enclClass.sym.type.asSuper(site.tsym); if (site1 != null) site = site1; } } if (((AttrContext) env.info).isSelfCall && tree.name == names._this && site.tsym == env.enclClass.sym) { chk.earlyRefError(tree.pos, sym); } } ((AttrContext) env.info).selectSuper = selectSuperPrev; result = checkId(tree, site, sym, env, pkind, pt); ((AttrContext) env.info).tvars = Type.emptyList; } /** * Determine symbol referenced by a Select expression, * * @param tree The select tree. * @param site The type of the selected expression, * @param env The current environment. * @param pt The current prototype. * @param pkind The expected kind(s) of the Select expression. */ private Symbol selectSym(Select tree, Type site, Env env, Type pt, int pkind) { int pos = tree.pos; Name name = tree.name; switch (site.tag) { case PACKAGE: return rs.access(rs.findIdentInPackage(env, site.tsym, name, pkind), pos, site, name, true); case ARRAY: case CLASS: if (pt.tag == METHOD) { return rs.resolveQualifiedMethod(pos, env, site, name, pt.argtypes()); } else if (name == names._this || name == names._super) { return rs.resolveSelf(pos, env, site.tsym, name); } else if (name == names._class) { return new VarSymbol(STATIC | PUBLIC | FINAL, names._class, syms.classType, site.tsym); } else { return rs.access(rs.findIdentInType(env, site, name, pkind), pos, site, name, true); } case ERROR: return new ErrorType(name, site.tsym).tsym; default: if (name == names._class) { return new VarSymbol(STATIC | PUBLIC | FINAL, names._class, syms.classType, site.tsym); } else { log.error(pos, "cant.deref", site.toJava()); return syms.errSymbol; } } } /** * Determine type of identifier or select expression and check that * (1) the referenced symbol is not deprecated * (2) the symbol's type is safe (@see checkSafe) * (3) if symbol is a variable, check that its type and kind are * compatible with the prototype and protokind. * (4) if symbol is an instance field of a raw type, * which is being assigned to, issue an unchecked warning if its * type changes under erasure. * (5) if symbol is an instance method of a raw type, issue an * unchecked warning if its argument types change under erasure. * If checks succeed: * If symbol is a constant, return its constant type * else if symbol is a method, return its result type * otherwise return its type. * Otherwise return errType. * * @param tree The syntax tree representing the identifier * @param site If this is a select, the type of the selected * expression, otherwise the type of the current class. * @param sym The symbol representing the identifier. * @param env The current environment. * @param pkind The set of expected kinds. * @param pt The expected type. */ Type checkId(Tree tree, Type site, Symbol sym, Env env, int pkind, Type pt) { Type owntype; switch (sym.kind) { case TYP: owntype = sym.type; if (owntype.tag == CLASS) { Type ownOuter = owntype.outer(); if (ownOuter.tag == CLASS && site != ownOuter) { Type normSite = site; if (normSite.tag == CLASS) normSite = site.asOuterSuper(ownOuter.tsym); if (normSite != ownOuter) owntype = new ClassType(normSite, Type.emptyList, owntype.tsym); } } break; case VAR: VarSymbol v = (VarSymbol) sym; owntype = (sym.owner.kind == TYP && sym.name != names._this && sym.name != names._super) ? site.memberType(sym) : sym.type; if (v.constValue != null && isStaticReference(tree)) owntype = owntype.constType(v.constValue); break; case MTH: owntype = rs.instantiate(env, site, sym, pt.argtypes()); if (owntype == null && Type.isDerivedRaw(pt.argtypes()) && !((AttrContext) env.info).rawArgs) { ((AttrContext) env.info).rawArgs = true; owntype = rs.instantiate(env, site, sym, pt.argtypes()); ((AttrContext) env.info).rawArgs = false; } if (owntype == null) { log.error(tree.pos, "internal.error.cant.instantiate", sym.toJava(), site.toJava(), Type.toJavaList(pt.argtypes())); } break; case PCK: case ERR: owntype = sym.type; break; default: throw new AssertionError("unexpected kind: " + sym.kind + " in tree " + tree); } if (sym.name != names.init && (sym.flags() & DEPRECATED) != 0 && (((AttrContext) env.info).scope.owner.flags() & DEPRECATED) == 0 && sym.outermostClass() != ((AttrContext) env.info).scope.owner.outermostClass()) chk.warnDeprecated(tree.pos, sym); return check(tree, owntype, sym.kind, pkind, pt); } /** * Check that variable is initialized and evaluate the variable's * initializer, if not yet done. Also check that variable is not * referenced before it is defined. * @param tree The tree making up the variable reference. * @param env The current environment. * @param v The variable's symbol. */ private void checkInit(Ident tree, Env env, VarSymbol v) { if (v.pos > tree.pos && v.owner.kind == TYP && canOwnInitializer(((AttrContext) env.info).scope.owner) && v.owner == ((AttrContext) env.info).scope.owner.enclClass() && ((v.flags() & STATIC) != 0) == Resolve.isStatic(env) && (env.tree.tag != Tree.ASSIGN || TreeInfo.skipParens(((Assign) env.tree).lhs) != tree)) log.error(tree.pos, "illegal.forward.ref"); evalInit(v); } /** * Can the given symbol be the owner of code which forms part * if class initialization? This is the case if the symbol is * a type or field, or if the symbol is the synthetic method. * owning a block. */ private boolean canOwnInitializer(Symbol sym) { return (sym.kind & (VAR | TYP)) != 0 || (sym.kind == MTH && (sym.flags() & BLOCK) != 0); } /** * Evaluate a final variable's initializer, unless this has already been * done, and set variable's constant value, if the initializer is * constant. */ public void evalInit(VarSymbol v) { if (v.constValue instanceof AttrContextEnv) { AttrContextEnv evalEnv = (AttrContextEnv) v.constValue; Name prev = log.useSource(evalEnv.toplevel.sourcefile); v.constValue = null; Type itype = attribExpr(((VarDef) evalEnv.tree).init, evalEnv, v.type); if (itype.constValue != null) v.constValue = cfolder.coerce(itype, v.type).constValue; log.useSource(prev); } } public void visitLiteral(Literal tree) { result = check(tree, litType(tree.typetag).constType(tree.value), VAL, pkind, pt); } /** * Return the type of a literal with given type tag. */ Type litType(int tag) { return (tag == CLASS) ? syms.stringType : syms.typeOfTag[tag]; } public void visitTypeIdent(TypeIdent tree) { result = check(tree, syms.typeOfTag[tree.typetag], TYP, pkind, pt); } public void visitTypeArray(TypeArray tree) { Type etype = attribType(tree.elemtype, env); result = check(tree, new ArrayType(etype, syms.arrayClass), TYP, pkind, pt); } public void visitErroneous(Erroneous tree) { result = tree.type = syms.errType; } /** * Default visitor method for all other trees. */ public void visitTree(Tree tree) { throw new AssertionError(); } /** * Main method: attribute class definition associated with given class symbol. * reporting completion failures at the given position. * @param pos The source position at which completion errors are to be * reported. * @param c The class symbol whose definition will be attributed. */ public void attribClass(int pos, ClassSymbol c) { try { attribClass(c); } catch (CompletionFailure ex) { chk.completionError(pos, ex); } } /** * Attribute class definition associated with given class symbol. * @param c The class symbol whose definition will be attributed. */ void attribClass(ClassSymbol c) throws CompletionFailure { if (c.type.tag == ERROR) return; chk.checkNonCyclic(Position.NOPOS, c.type); Type st = c.type.supertype(); if (st.tag == CLASS) attribClass((ClassSymbol) st.tsym); if (c.owner.kind == TYP && c.owner.type.tag == CLASS) attribClass((ClassSymbol) c.owner); if ((c.flags_field & UNATTRIBUTED) != 0) { c.flags_field &= ~UNATTRIBUTED; Env env = (Env) enter.classEnvs.remove(c); Name prev = log.useSource(c.sourcefile); try { attribClassBody(env, c); } finally { log.useSource(prev); } } } /** * Finish the attribution of a class. */ private void attribClassBody(Env env, ClassSymbol c) { ClassDef tree = (ClassDef) env.tree; assert c == tree.sym; chk.validate(tree.extending); chk.validate(tree.implementing); if ((c.flags() & (ABSTRACT | INTERFACE)) == 0) { if (!retrofit) chk.checkAllDefined(tree.pos, c); } else chk.checkCompatibleSupertypes(tree.pos, c.type); tree.type = c.type; chk.checkImplementations(tree); for (List l = tree.defs; l.nonEmpty(); l = l.tail) { attribStat((Tree) l.head, env); if (c.owner.kind != PCK && ((c.flags() & STATIC) == 0 || c.name == names.empty) && (TreeInfo.flags((Tree) l.head) & (STATIC | INTERFACE)) != 0) { Symbol sym = null; if (((Tree) l.head).tag == Tree.VARDEF) sym = ((VarDef) l.head).sym; if (sym == null || sym.kind != VAR || ((VarSymbol) sym).constValue == null) log.error(((Tree) l.head).pos, "icls.cant.have.static.decl"); } } chk.checkCyclicConstructors(tree); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -