attr.java

来自「是一款用JAVA 编写的编译器 具有很强的编译功能」· Java 代码 · 共 1,568 行 · 第 1/5 页

JAVA
1,568
字号
/* * 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 java.util.*;import java.util.Set;import javax.lang.model.element.ElementKind;import javax.tools.JavaFileObject;import com.sun.tools.javac.code.*;import com.sun.tools.javac.jvm.*;import com.sun.tools.javac.tree.*;import com.sun.tools.javac.util.*;import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;import com.sun.tools.javac.util.List;import com.sun.tools.javac.jvm.Target;import com.sun.tools.javac.code.Symbol.*;import com.sun.tools.javac.tree.JCTree.*;import com.sun.tools.javac.code.Type.*;import com.sun.source.tree.IdentifierTree;import com.sun.source.tree.MemberSelectTree;import com.sun.source.tree.TreeVisitor;import com.sun.source.util.SimpleTreeVisitor;import static com.sun.tools.javac.code.Flags.*;import static com.sun.tools.javac.code.Kinds.*;import static com.sun.tools.javac.code.TypeTags.*;/** This is the main context-dependent analysis phase in GJC. It *  encompasses name resolution, type checking and constant folding as *  subtasks. Some subtasks involve auxiliary classes. *  @see Check *  @see Resolve *  @see ConstFold *  @see Infer * *  <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 Attr extends JCTree.Visitor {    protected static final Context.Key<Attr> attrKey =        new Context.Key<Attr>();    final Name.Table names;    final Log log;    final Symtab syms;    final Resolve rs;    final Check chk;    final MemberEnter memberEnter;    final TreeMaker make;    final ConstFold cfolder;    final Enter enter;    final Target target;    final Types types;    final Annotate annotate;    public static Attr instance(Context context) {        Attr instance = context.get(attrKey);        if (instance == null)            instance = new Attr(context);        return instance;    }    protected Attr(Context context) {        context.put(attrKey, this);        names = Name.Table.instance(context);        log = Log.instance(context);        syms = Symtab.instance(context);        rs = Resolve.instance(context);        chk = Check.instance(context);        memberEnter = MemberEnter.instance(context);        make = TreeMaker.instance(context);        enter = Enter.instance(context);        cfolder = ConstFold.instance(context);        target = Target.instance(context);        types = Types.instance(context);        annotate = Annotate.instance(context);        Options options = Options.instance(context);        Source source = Source.instance(context);        allowGenerics = source.allowGenerics();        allowVarargs = source.allowVarargs();        allowEnums = source.allowEnums();        allowBoxing = source.allowBoxing();        allowCovariantReturns = source.allowCovariantReturns();        allowAnonOuterThis = source.allowAnonOuterThis();        relax = (options.get("-retrofit") != null ||                 options.get("-relax") != null);        useBeforeDeclarationWarning = options.get("useBeforeDeclarationWarning") != null;    }    /** Switch: relax some constraints for retrofit mode.     */    boolean relax;    /** Switch: support generics?     */    boolean allowGenerics;    /** Switch: allow variable-arity methods.     */    boolean allowVarargs;    /** Switch: support enums?     */    boolean allowEnums;    /** Switch: support boxing and unboxing?     */    boolean allowBoxing;    /** Switch: support covariant result types?     */    boolean allowCovariantReturns;    /** Switch: allow references to surrounding object from anonymous     * objects during constructor call?     */    boolean allowAnonOuterThis;    /**     * Switch: warn about use of variable before declaration?     * RFE: 6425594     */    boolean useBeforeDeclarationWarning;    /** Check kind and type of given tree against protokind and prototype.     *  If check succeeds, store type in tree and return it.     *  If check fails, store errType in tree and return it.     *  No checks are performed if the prototype is a method type.     *  Its not necessary in this case since we know that kind and type     *  are correct.     *     *  @param tree     The tree whose kind and type is checked     *  @param owntype  The computed type of the tree     *  @param ownkind  The computed kind of the tree     *  @param pkind    The expected kind (or: protokind) of the tree     *  @param pt       The expected type (or: prototype) of the tree     */    Type check(JCTree tree, Type owntype, int ownkind, int pkind, Type pt) {        if (owntype.tag != ERROR && pt.tag != METHOD && pt.tag != FORALL) {            if ((ownkind & ~pkind) == 0) {                owntype = chk.checkType(tree.pos(), owntype, pt);            } else {                log.error(tree.pos(), "unexpected.type",                          Resolve.kindNames(pkind),                          Resolve.kindName(ownkind));                owntype = syms.errType;            }        }        tree.type = owntype;        return owntype;    }    /** Is given blank final variable assignable, i.e. in a scope where it     *  may be assigned to even though it is final?     *  @param v      The blank final variable.     *  @param env    The current environment.     */    boolean isAssignableAsBlankFinal(VarSymbol v, Env<AttrContext> env) {        Symbol owner = env.info.scope.owner;           // owner refers to the innermost variable, method or           // initializer block declaration at this point.        return            v.owner == owner            ||            ((owner.name == names.init ||    // i.e. we are in a constructor              owner.kind == VAR ||           // i.e. we are in a variable initializer              (owner.flags() & BLOCK) != 0)  // i.e. we are in an initializer block             &&             v.owner == owner.owner             &&             ((v.flags() & STATIC) != 0) == Resolve.isStatic(env));    }    /** Check that variable can be assigned to.     *  @param pos    The current source code position.     *  @param v      The assigned varaible     *  @param base   If the variable is referred to in a Select, the part     *                to the left of the `.', null otherwise.     *  @param env    The current environment.     */    void checkAssignable(DiagnosticPosition pos, VarSymbol v, JCTree base, Env<AttrContext> env) {        if ((v.flags() & FINAL) != 0 &&            ((v.flags() & HASINIT) != 0             ||             !((base == null ||               (base.getTag() == JCTree.IDENT && TreeInfo.name(base) == names._this)) &&               isAssignableAsBlankFinal(v, env)))) {            log.error(pos, "cant.assign.val.to.final.var", v);        }    }    /** Does tree represent a static reference to an identifier?     *  It is assumed that tree is either a SELECT or an IDENT.     *  We have to weed out selects from non-type names here.     *  @param tree    The candidate tree.     */    boolean isStaticReference(JCTree tree) {        if (tree.getTag() == JCTree.SELECT) {            Symbol lsym = TreeInfo.symbol(((JCFieldAccess) tree).selected);            if (lsym == null || lsym.kind != TYP) {                return false;            }        }        return true;    }    /** Is this symbol a type?     */    static boolean isType(Symbol sym) {        return sym != null && sym.kind == TYP;    }    /** The current `this' symbol.     *  @param env    The current environment.     */    Symbol thisSym(DiagnosticPosition pos, Env<AttrContext> env) {        return rs.resolveSelf(pos, env, env.enclClass.sym, names._this);    }    /** Attribute a parsed identifier.     * @param tree Parsed identifier name     * @param topLevel The toplevel to use     */    public Symbol attribIdent(JCTree tree, JCCompilationUnit topLevel) {        Env<AttrContext> localEnv = enter.topLevelEnv(topLevel);        localEnv.enclClass = make.ClassDef(make.Modifiers(0),                                           syms.errSymbol.name,                                           null, null, null, null);        localEnv.enclClass.sym = syms.errSymbol;        return tree.accept(identAttributer, localEnv);    }    // where        private TreeVisitor<Symbol,Env<AttrContext>> identAttributer = new IdentAttributer();        private class IdentAttributer extends SimpleTreeVisitor<Symbol,Env<AttrContext>> {            @Override            public Symbol visitMemberSelect(MemberSelectTree node, Env<AttrContext> env) {                Symbol site = visit(node.getExpression(), env);                if (site.kind == ERR)                    return site;                Name name = (Name)node.getIdentifier();                if (site.kind == PCK) {                    env.toplevel.packge = (PackageSymbol)site;                    return rs.findIdentInPackage(env, (TypeSymbol)site, name, TYP | PCK);                } else {                    env.enclClass.sym = (ClassSymbol)site;                    return rs.findMemberType(env, site.asType(), name, (TypeSymbol)site);                }            }                @Override            public Symbol visitIdentifier(IdentifierTree node, Env<AttrContext> env) {                return rs.findIdent(env, (Name)node.getName(), TYP | PCK);            }        }    public Type coerce(Type etype, Type ttype) {        return cfolder.coerce(etype, ttype);    }    public Type attribType(JCTree node, TypeSymbol sym) {        Env<AttrContext> env = enter.typeEnvs.get(sym);        Env<AttrContext> localEnv = env.dup(node, env.info.dup());        return attribTree(node, localEnv, Kinds.TYP, Type.noType);    }      public Env<AttrContext> attribExprToTree(JCTree expr, Env<AttrContext> env, JCTree tree) {        breakTree = tree;        JavaFileObject prev = log.useSource(null);        try {            attribExpr(expr, env);        } catch (BreakAttr b) {            return b.env;        } finally {            breakTree = null;            log.useSource(prev);        }        return env;    }        public Env<AttrContext> attribStatToTree(JCTree stmt, Env<AttrContext> env, JCTree tree) {        breakTree = tree;        JavaFileObject prev = log.useSource(null);        try {

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?