⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 resolve.java

📁 java编译器gjc源码 java编译环境
💻 JAVA
📖 第 1 页 / 共 4 页
字号:
/**
 * @(#)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 + -