📄 resolve.java
字号:
/**
* @(#)Resolve.java 1.67 03/05/06
*
* Copyright 2003 Sun Microsystems, Inc. All rights reserved.
* SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*/
package com.sun.tools.javac.v8.comp;
import com.sun.tools.javac.v8.util.*;
import com.sun.tools.javac.v8.code.*;
import com.sun.tools.javac.v8.tree.*;
import com.sun.tools.javac.v8.code.Type.*;
import com.sun.tools.javac.v8.code.Symbol.*;
import com.sun.tools.javac.v8.tree.Tree.*;
/**
* Helper class for name resolution, used mostly by the attribution phase.
*/
public class Resolve implements Flags, Kinds, TypeTags {
private static final Context.Key resolveKey = new Context.Key();
private Name.Table names;
private Log log;
private Symtab syms;
private Check chk;
private Infer infer;
private ClassReader reader;
private TreeInfo treeinfo;
public static Resolve instance(Context context) {
Resolve instance = (Resolve) context.get(resolveKey);
if (instance == null)
instance = new Resolve(context);
return instance;
}
private Resolve(Context context) {
super();
context.put(resolveKey, this);
syms = Symtab.instance(context);
varNotFound = new ResolveError(ABSENT_VAR, syms.errSymbol, "variable not found");
wrongMethod = new ResolveError(WRONG_MTH, syms.errSymbol, "method not found");
wrongMethods = new ResolveError(WRONG_MTHS, syms.errSymbol, "wrong methods");
methodNotFound = new ResolveError(ABSENT_MTH, syms.errSymbol, "method not found");
typeNotFound = new ResolveError(ABSENT_TYP, syms.errSymbol, "type not found");
names = Name.Table.instance(context);
log = Log.instance(context);
chk = Check.instance(context);
infer = Infer.instance(context);
reader = ClassReader.instance(context);
treeinfo = TreeInfo.instance(context);
}
/**
* Error kinds that complement the constants in Kinds
*/
static final int AMBIGUOUS = 256;
static final int HIDDEN = 257;
static final int ABSENT_VAR = 258;
static final int WRONG_MTHS = 259;
static final int WRONG_MTH = 260;
static final int ABSENT_MTH = 261;
static final int ABSENT_TYP = 262;
/**
* error symbols, which are returned when resolution fails
*/
final ResolveError varNotFound;
final ResolveError wrongMethod;
final ResolveError wrongMethods;
final ResolveError methodNotFound;
final ResolveError typeNotFound;
/**
* An environment is "static" if its static level is greater than
* the one of its outer environment
*/
static boolean isStatic(Env env) {
return ((AttrContext) env.info).staticLevel >
((AttrContext) env.outer.info).staticLevel;
}
/**
* The static level of a symbol is the number of prefixing static flags
* for the symbol and any enclosing class or member declarations.
*/
static int staticLevel(Symbol sym) {
int level = 0;
do {
if ((sym.flags() & STATIC) != 0)
level++;
sym = sym.owner;
} while (sym.kind != PCK)
;
return level;
}
/**
* Is class accessible in given evironment?
* @param env The current environment.
* @param c The class whose accessibility is checked.
*/
boolean isAccessible(Env env, TypeSymbol c) {
switch ((short)(c.flags() & AccessFlags)) {
case PRIVATE:
return env.enclClass.sym.outermostClass() == c.owner.outermostClass();
case 0:
return env.toplevel.packge == c.owner ||
env.toplevel.packge == c.packge() || env.enclMethod != null &&
(env.enclMethod.flags & ANONCONSTR) != 0;
case PUBLIC:
return true;
case PROTECTED:
return env.toplevel.packge == c.owner ||
env.toplevel.packge == c.packge() ||
isInnerSubClass(env.enclClass.sym, c.owner);
default:
return true;
}
}
/**
* Is given class a subclass of given base class, or an inner class
* of a subclass?
* Return null if no such class exists.
* @param c The class which is the subclass or is contained in it.
* @param base The base class
*/
private boolean isInnerSubClass(ClassSymbol c, Symbol base) {
while (c != null && !c.isSubClass(base)) {
c = c.owner.enclClass();
}
return c != null;
}
boolean isAccessible(Env env, Type t) {
return (t.tag == ARRAY) ? isAccessible(env, t.elemtype()) :
isAccessible(env, t.tsym);
}
/**
* Is symbol accessible as a member of given type in given evironment?
* @param env The current environment.
* @param site The type of which the tested symbol is regarded
* as a member.
* @param sym The symbol.
*/
boolean isAccessible(Env env, Type site, Symbol sym) {
if (sym.name == names.init && sym.owner != site.tsym)
return false;
ClassSymbol sub;
switch ((short)(sym.flags() & AccessFlags)) {
case PRIVATE:
return (env.enclClass.sym == sym.owner ||
env.enclClass.sym.outermostClass() ==
sym.owner.outermostClass()) && sym.isInheritedIn(site.tsym);
case 0:
return (env.toplevel.packge == sym.owner.owner ||
env.toplevel.packge == sym.packge()) &&
sym.isInheritedIn(site.tsym);
case PROTECTED:
return (env.toplevel.packge == sym.owner.owner ||
env.toplevel.packge == sym.packge() ||
isProtectedAccessible(sym, env.enclClass.sym, site) ||
((AttrContext) env.info).selectSuper &&
(sym.flags() & STATIC) == 0 && sym.kind != TYP) &&
(sym.kind != MTH || sym.isConstructor() ||
((MethodSymbol) sym).implementation(site.tsym) == sym);
default:
return isAccessible(env, site);
}
}
/**
* Is given protected symbol accessible if it is selected from given site
* and the selection takes place in given class?
* @param sym The symbol with protected access
* @param c The class where the access takes place
* @site The type of the qualifier
*/
private boolean isProtectedAccessible(Symbol sym, ClassSymbol c, Type site) {
while (c != null &&
!(c.isSubClass(sym.owner) && (c.flags() & INTERFACE) == 0 &&
((sym.flags() & STATIC) != 0 || sym.kind == TYP ||
site.tsym.isSubClass(c))))
c = c.owner.enclClass();
return c != null;
}
/**
* Try to instantiate the type of a method so that it fits
* given type parameters and argument types. If succesful, return
* the method's instantiated type, else return null.
* The instantiation will take into account an additional leading
* formal parameter if the method is an instance method seen as a member
* of un underdetermined site In this case, we treat site as an additional
* parameter and the parameters of the class containing the method as
* additional type variables that get instantiated.
*
* @param env The current environment
* @param site The type of which the method is a member.
* @param m The method symbol.
* @param argtypes The invocation's given value parameters.
*/
Type instantiate(Env env, Type site, Symbol m, List argtypes) {
Type mt = site.memberType(m);
List formals = mt.argtypes();
return (Type.isSubTypes(argtypes, formals)) ? mt : null;
}
/**
* Find field. Synthetic fields are always skipped.
* @param env The current environment.
* @param site The original type from where the selection takes place.
* @param name The name of the field.
* @param c The class to search for the field. This is always
* a superclass or implemented interface of site's class.
*/
Symbol findField(Env env, Type site, Name name, TypeSymbol c) {
Symbol bestSoFar = varNotFound;
Symbol sym;
Scope.Entry e = c.members().lookup(name);
while (e.scope != null) {
if (e.sym.kind == VAR && (e.sym.flags_field & SYNTHETIC) == 0) {
if (isAccessible(env, site, e.sym))
return e.sym;
else
return new AccessError(e.sym);
}
e = e.next();
}
Type st = c.type.supertype();
if (st != null && st.tag == CLASS) {
sym = findField(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 = findField(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 unqualified variable or field with given name.
* Synthetic fields always skipped.
* @param env The current environment.
* @param name The name of the variable or field.
*/
Symbol findVar(Env env, Name name) {
Symbol bestSoFar = varNotFound;
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 &&
(e.sym.kind != VAR || (e.sym.flags_field & SYNTHETIC) != 0))
e = e.next();
sym = (e.scope != null) ? e.sym :
findField(env1, env1.enclClass.sym.type, name,
env1.enclClass.sym);
if (sym.kind <= AMBIGUOUS) {
if (staticOnly && sym.kind == VAR && 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 = findField(env, syms.predefClass.type, name, syms.predefClass);
if (sym.kind <= AMBIGUOUS)
return sym;
else
return bestSoFar;
}
/**
* Select the best method for a call site among two choices.
* @param env The current environment.
* @param site The original type from where the selection takes place.
* @param argtypes The invocation's value parameters,
* @param sym Proposed new best match.
* @param bestSoFar Previously found best match.
*/
Symbol selectBest(Env env, Type site, List argtypes, Symbol sym,
Symbol bestSoFar) {
if (sym.kind == ERR)
return bestSoFar;
assert sym.kind < AMBIGUOUS;
if (instantiate(env, site, sym, argtypes) == null) {
switch (bestSoFar.kind) {
case ABSENT_MTH:
return wrongMethod.setWrongSym(sym);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -