resolve.java
来自「是一款用JAVA 编写的编译器 具有很强的编译功能」· Java 代码 · 共 1,519 行 · 第 1/5 页
JAVA
1,519 行
/* * Copyright 1999-2006 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Sun designates this * particular file as subject to the "Classpath" exception as provided * by Sun in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, * CA 95054 USA or visit www.sun.com if you need additional information or * have any questions. */package com.sun.tools.javac.comp;import com.sun.tools.javac.util.*;import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;import com.sun.tools.javac.code.*;import com.sun.tools.javac.jvm.*;import com.sun.tools.javac.tree.*;import com.sun.tools.javac.code.Type.*;import com.sun.tools.javac.code.Symbol.*;import com.sun.tools.javac.tree.JCTree.*;import static com.sun.tools.javac.code.Flags.*;import static com.sun.tools.javac.code.Kinds.*;import static com.sun.tools.javac.code.TypeTags.*;import javax.lang.model.element.ElementVisitor;/** Helper class for name resolution, used mostly by the attribution phase. * * <p><b>This is NOT part of any API supported by Sun Microsystems. If * you write code that depends on this, you do so at your own risk. * This code and its internal interfaces are subject to change or * deletion without notice.</b> */public class Resolve { protected static final Context.Key<Resolve> resolveKey = new Context.Key<Resolve>(); Name.Table names; Log log; Symtab syms; Check chk; Infer infer; ClassReader reader; TreeInfo treeinfo; Types types; public final boolean boxingEnabled; // = source.allowBoxing(); public final boolean varargsEnabled; // = source.allowVarargs(); private final boolean debugResolve; public static Resolve instance(Context context) { Resolve instance = context.get(resolveKey); if (instance == null) instance = new Resolve(context); return instance; } protected Resolve(Context context) { 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); types = Types.instance(context); Source source = Source.instance(context); boxingEnabled = source.allowBoxing(); varargsEnabled = source.allowVarargs(); Options options = Options.instance(context); debugResolve = options.get("debugresolve") != null; } /** error symbols, which are returned when resolution fails */ final ResolveError varNotFound; final ResolveError wrongMethod; final ResolveError wrongMethods; final ResolveError methodNotFound; final ResolveError typeNotFound;/* ************************************************************************ * Identifier resolution *************************************************************************/ /** An environment is "static" if its static level is greater than * the one of its outer environment */ static boolean isStatic(Env<AttrContext> env) { return env.info.staticLevel > env.outer.info.staticLevel; } /** An environment is an "initializer" if it is a constructor or * an instance initializer. */ static boolean isInitializer(Env<AttrContext> env) { Symbol owner = env.info.scope.owner; return owner.isConstructor() || owner.owner.kind == TYP && (owner.kind == VAR || owner.kind == MTH && (owner.flags() & BLOCK) != 0) && (owner.flags() & STATIC) == 0; } /** Is class accessible in given evironment? * @param env The current environment. * @param c The class whose accessibility is checked. */ public boolean isAccessible(Env<AttrContext> 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 // fast special case || env.toplevel.packge == c.packge() || // Hack: this case is added since synthesized default constructors // of anonymous classes should be allowed to access // classes which would be inaccessible otherwise. env.enclMethod != null && (env.enclMethod.mods.flags & ANONCONSTR) != 0; default: // error recovery case PUBLIC: return true; case PROTECTED: return env.toplevel.packge == c.owner // fast special case || env.toplevel.packge == c.packge() || isInnerSubClass(env.enclClass.sym, c.owner); } } //where /** 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, types)) { c = c.owner.enclClass(); } return c != null; } boolean isAccessible(Env<AttrContext> env, Type t) { return (t.tag == ARRAY) ? isAccessible(env, types.elemtype(t)) : 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. */ public boolean isAccessible(Env<AttrContext> 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 // fast special case || env.enclClass.sym.outermostClass() == sym.owner.outermostClass()) && sym.isInheritedIn(site.tsym, types); case 0: return (env.toplevel.packge == sym.owner.owner // fast special case || env.toplevel.packge == sym.packge()) && isAccessible(env, site) && sym.isInheritedIn(site.tsym, types); case PROTECTED: return (env.toplevel.packge == sym.owner.owner // fast special case || env.toplevel.packge == sym.packge() || isProtectedAccessible(sym, env.enclClass.sym, site) || // OK to select instance method or field from 'super' or type name // (but type names should be disallowed elsewhere!) env.info.selectSuper && (sym.flags() & STATIC) == 0 && sym.kind != TYP) && isAccessible(env, site) && // `sym' is accessible only if not overridden by // another symbol which is a member of `site' // (because, if it is overridden, `sym' is not strictly // speaking a member of `site'.) (sym.kind != MTH || sym.isConstructor() || ((MethodSymbol)sym).implementation(site.tsym, types, true) == sym); default: // this case includes erroneous combinations as well return isAccessible(env, site); } } //where /** 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, types) && (c.flags() & INTERFACE) == 0 && // In JLS 2e 6.6.2.1, the subclass restriction applies // only to instance fields and methods -- types are excluded // regardless of whether they are declared 'static' or not. ((sym.flags() & STATIC) != 0 || sym.kind == TYP || site.tsym.isSubClass(c, types)))) c = c.owner.enclClass(); return c != null; } /** Try to instantiate the type of a method so that it fits * given type arguments 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 arguments. * @param typeargtypes The invocation's given type arguments. * @param allowBoxing Allow boxing conversions of arguments. * @param useVarargs Box trailing arguments into an array for varargs. */ Type rawInstantiate(Env<AttrContext> env, Type site, Symbol m, List<Type> argtypes, List<Type> typeargtypes, boolean allowBoxing, boolean useVarargs, Warner warn) throws Infer.NoInstanceException { if (useVarargs && (m.flags() & VARARGS) == 0) return null; Type mt = types.memberType(site, m); // tvars is the list of formal type variables for which type arguments // need to inferred. List<Type> tvars = env.info.tvars; if (typeargtypes == null) typeargtypes = List.nil(); if (mt.tag != FORALL && typeargtypes.nonEmpty()) { // This is not a polymorphic method, but typeargs are supplied // which is fine, see JLS3 15.12.2.1 } else if (mt.tag == FORALL && typeargtypes.nonEmpty()) { ForAll pmt = (ForAll) mt; if (typeargtypes.length() != pmt.tvars.length()) return null; // Check type arguments are within bounds List<Type> formals = pmt.tvars; List<Type> actuals = typeargtypes; while (formals.nonEmpty() && actuals.nonEmpty()) { List<Type> bounds = types.subst(types.getBounds((TypeVar)formals.head), pmt.tvars, typeargtypes); for (; bounds.nonEmpty(); bounds = bounds.tail) if (!types.isSubtypeUnchecked(actuals.head, bounds.head, warn))
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?