📄 resolve.java
字号:
case WRONG_MTH:
return wrongMethods;
default:
return bestSoFar;
}
}
if (!isAccessible(env, site, sym)) {
return (bestSoFar.kind == ABSENT_MTH) ? new AccessError(sym) : bestSoFar;
}
return (bestSoFar.kind > AMBIGUOUS) ? sym :
mostSpecific(sym, bestSoFar, env, site);
}
Symbol mostSpecific(Symbol m1, Symbol m2, Env env, Type site) {
switch (m2.kind) {
case MTH:
if (m1 == m2)
return m1;
Type mt1 = site.memberType(m1);
boolean m1SignatureMoreSpecific =
instantiate(env, site, m2, mt1.argtypes()) != null;
Type mt2 = site.memberType(m2);
boolean m2SignatureMoreSpecific =
instantiate(env, site, m1, mt2.argtypes()) != null;
if (m1SignatureMoreSpecific && m2SignatureMoreSpecific) {
if (methodsInherited(m1.owner, m2.owner))
return m1;
if (methodsInherited(m2.owner, m1.owner))
return m2;
boolean m1Abstract = (m1.flags() & ABSTRACT) != 0;
if (!m1Abstract)
return m1;
boolean m2Abstract = (m2.flags() & ABSTRACT) != 0;
if (!m2Abstract)
return m2;
Symbol result = mt1.restype().isSubType(mt2.restype()) ? m1 : m2;
result = result.clone(result.owner);
result.type = (Type) result.type.clone();
result.type.setThrown(Check.intersect(mt1.thrown(), mt2.thrown()));
return result;
}
if (m1SignatureMoreSpecific)
return m1;
if (m2SignatureMoreSpecific)
return m2;
return new AmbiguityError(m1, m2);
case AMBIGUOUS:
AmbiguityError e = (AmbiguityError) m2;
Symbol err1 = mostSpecific(m1, e.sym1, env, site);
Symbol err2 = mostSpecific(m1, e.sym2, env, site);
if (err1 == err2)
return err1;
if (err1 == e.sym1 && err2 == e.sym2)
return m2;
return new AmbiguityError(err1, err2);
default:
throw new AssertionError();
}
}
private boolean methodsInherited(Symbol subclass, Symbol superclass) {
return subclass.isSubClass(superclass) &&
!((subclass.flags() & INTERFACE) != 0 &&
superclass.type == syms.objectType);
}
/**
* Find best qualified method matching given name, type and value parameters.
* @param env The current environment.
* @param site The original type from where the selection takes place.
* @param name The method's name.
* @param argtypes The method's value parameters.
*/
Symbol findMethod(Env env, Type site, Name name, List argtypes) {
return findMethod(env, site, name, argtypes, site.tsym.type, true,
methodNotFound);
}
private Symbol findMethod(Env env, Type site, Name name, List argtypes,
Type intype, boolean abstractok, Symbol bestSoFar) {
for (Type ct = intype; ct.tag == CLASS; ct = ct.supertype()) {
ClassSymbol c = (ClassSymbol) ct.tsym;
if ((c.flags() & (ABSTRACT | INTERFACE)) == 0)
abstractok = false;
for (Scope.Entry e = c.members().lookup(name); e.scope != null;
e = e.next()) {
if (e.sym.kind == MTH && (e.sym.flags_field & SYNTHETIC) == 0) {
bestSoFar = selectBest(env, site, argtypes, e.sym, bestSoFar);
}
}
if (abstractok) {
for (List l = c.type.interfaces(); l.nonEmpty(); l = l.tail) {
bestSoFar = findMethod(env, site, name, argtypes, (Type) l.head,
abstractok, bestSoFar);
}
}
}
return bestSoFar;
}
/**
* Find unqualified method matching given name, type and value parameters.
* @param env The current environment.
* @param name The method's name.
* @param argtypes The method's value parameters.
*/
Symbol findFun(Env env, Name name, List argtypes) {
Symbol bestSoFar = methodNotFound;
Symbol sym;
Env env1 = env;
boolean staticOnly = false;
while (env1.outer != null) {
if (isStatic(env1))
staticOnly = true;
sym = findMethod(env1, env1.enclClass.sym.type, name, argtypes);
if (sym.kind <= AMBIGUOUS || sym.kind == WRONG_MTHS ||
sym.kind == WRONG_MTH) {
if (staticOnly && sym.kind == MTH && sym.owner.kind == TYP &&
(sym.flags() & STATIC) == 0)
return new StaticError(sym);
else
return sym;
} else if (sym.kind < bestSoFar.kind) {
bestSoFar = sym;
}
if ((env1.enclClass.sym.flags() & STATIC) != 0)
staticOnly = true;
env1 = env1.outer;
}
sym = findMethod(env, syms.predefClass.type, name, argtypes);
if (sym.kind <= AMBIGUOUS)
return sym;
else
return bestSoFar;
}
/**
* Load toplevel or member class with given fully qualified name and
* verify that it is accessible.
* @param env The current environment.
* @param name The fully qualified name of the class to be loaded.
*/
Symbol loadClass(Env env, Name name) {
try {
ClassSymbol c = reader.loadClass(name);
if (isAccessible(env, c))
return c;
else
return new AccessError(c);
} catch (ClassReader.BadClassFile err) {
throw err;
}
catch (CompletionFailure ex) {
return typeNotFound;
}
}
/**
* Find qualified member type.
* @param env The current environment.
* @param site The original type from where the selection takes place.
* @param name The type's name.
* @param c The class to search for the member type. This is always
* a superclass or implemented interface of site's class.
*/
Symbol findMemberType(Env env, Type site, Name name, TypeSymbol c) {
Symbol bestSoFar = typeNotFound;
Symbol sym;
Scope.Entry e = c.members().lookup(name);
while (e.scope != null) {
if (e.sym.kind == TYP) {
return isAccessible(env, site, e.sym) ? e.sym :
new AccessError(e.sym);
}
e = e.next();
}
Type st = c.type.supertype();
if (st != null && st.tag == CLASS) {
sym = findMemberType(env, site, name, st.tsym);
if (sym.kind < bestSoFar.kind)
bestSoFar = sym;
}
for (List l = c.type.interfaces();
bestSoFar.kind != AMBIGUOUS && l.nonEmpty(); l = l.tail) {
sym = findMemberType(env, site, name, ((Type) l.head).tsym);
if (bestSoFar.kind < AMBIGUOUS && sym.kind < AMBIGUOUS &&
sym.owner != bestSoFar.owner)
bestSoFar = new AmbiguityError(bestSoFar, sym);
else if (sym.kind < bestSoFar.kind)
bestSoFar = sym;
}
return bestSoFar;
}
/**
* Find a global type in given scope and load corresponding class.
* @param env The current environment.
* @param scope The scope in which to look for the type.
* @param name The type's name.
*/
Symbol findGlobalType(Env env, Scope scope, Name name) {
Symbol bestSoFar = typeNotFound;
Scope.Entry e = scope.lookup(name);
while (e.scope != null) {
if (e.scope.owner == e.sym.owner) {
Symbol sym = loadClass(env, e.sym.flatName());
if (bestSoFar.kind == TYP && sym.kind == TYP && bestSoFar != sym)
return new AmbiguityError(bestSoFar, sym);
else if (sym.kind < bestSoFar.kind)
bestSoFar = sym;
}
e = e.next();
}
return bestSoFar;
}
/**
* Find an unqualified type symbol.
* @param env The current environment.
* @param name The type's name.
*/
Symbol findType(Env env, Name name) {
Symbol bestSoFar = typeNotFound;
Symbol sym;
Env env1 = env;
boolean staticOnly = false;
while (env1.outer != null) {
if (isStatic(env1))
staticOnly = true;
Scope.Entry e = ((AttrContext) env1.info).scope.lookup(name);
while (e.scope != null) {
if (e.sym.kind == TYP) {
return e.sym;
}
e = e.next();
}
sym = findMemberType(env1, env1.enclClass.sym.type, name,
env1.enclClass.sym);
if (staticOnly && sym.kind == TYP && sym.type.tag == CLASS &&
sym.type.outer().isParameterized())
return new StaticError(sym);
else if (sym.kind <= AMBIGUOUS)
return sym;
else if (sym.kind < bestSoFar.kind)
bestSoFar = sym;
long flags = env1.enclClass.sym.flags();
if ((flags & STATIC) != 0)
staticOnly = true;
env1 = env1.outer;
}
if (env.tree.tag != Tree.IMPORT) {
sym = findGlobalType(env, env.toplevel.namedImportScope, name);
if (sym.kind <= AMBIGUOUS)
return sym;
else if (sym.kind < bestSoFar.kind)
bestSoFar = sym;
sym = findGlobalType(env, env.toplevel.packge.members(), name);
if (sym.kind <= AMBIGUOUS)
return sym;
else if (sym.kind < bestSoFar.kind)
bestSoFar = sym;
sym = findGlobalType(env, env.toplevel.starImportScope, name);
if (sym.kind <= AMBIGUOUS)
return sym;
else if (sym.kind < bestSoFar.kind)
bestSoFar = sym;
}
return bestSoFar;
}
/**
* Find an unqualified identifier which matches a specified kind set.
* @param env The current environment.
* @param name The indentifier's name.
* @param kind Indicates the possible symbol kinds
* (a subset of VAL, TYP, PCK).
*/
Symbol findIdent(Env env, Name name, int kind) {
Symbol bestSoFar = typeNotFound;
Symbol sym;
if ((kind & VAR) != 0) {
sym = findVar(env, name);
if (sym.kind <= AMBIGUOUS)
return sym;
else if (sym.kind < bestSoFar.kind)
bestSoFar = sym;
}
if ((kind & TYP) != 0) {
sym = findType(env, name);
if (sym.kind <= AMBIGUOUS)
return sym;
else if (sym.kind < bestSoFar.kind)
bestSoFar = sym;
}
if ((kind & PCK) != 0)
return reader.enterPackage(name);
else
return bestSoFar;
}
/**
* Find an identifier in a package which matches a specified kind set.
* @param env The current environment.
* @param name The identifier's name.
* @param kind Indicates the possible symbol kinds
* (a nonempty subset of TYP, PCK).
*/
Symbol findIdentInPackage(Env env, TypeSymbol pck, Name name, int kind) {
Name fullname = TypeSymbol.formFullName(name, pck);
Symbol bestSoFar = typeNotFound;
PackageSymbol pack = null;
if ((kind & PCK) != 0) {
pack = reader.enterPackage(fullname);
if (pack.exists())
return pack;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -