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