📄 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 + -