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 + -
显示快捷键?