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

📄 attr.java

📁 java编译器gjc源码 java编译环境
💻 JAVA
📖 第 1 页 / 共 4 页
字号:
                checkAssignable(tree.pos, v, null, env);
        }
        if ((((AttrContext) symEnv.info).isSelfCall || noOuterThisPath) &&
                (sym.kind & (VAR | MTH)) != 0 && sym.owner.kind == TYP &&
                (sym.flags() & STATIC) == 0) {
            chk.earlyRefError(tree.pos, sym.kind == VAR ? sym : thisSym(env));
        }
        result = checkId(tree, env.enclClass.sym.type, sym, env, pkind, pt);
    }

    public void visitSelect(Select tree) {
        int skind = 0;
        if (tree.name == names._this || tree.name == names._super ||
                tree.name == names._class) {
            skind = TYP;
        } else {
            if ((pkind & PCK) != 0)
                skind = skind | PCK;
            if ((pkind & TYP) != 0)
                skind = skind | TYP | PCK;
            if ((pkind & (VAL | MTH)) != 0)
                skind = skind | VAL | TYP;
        }
        Type site = attribTree(tree.selected, env, skind, Infer.anyPoly);
        Symbol sitesym = TreeInfo.symbol(tree.selected);
        boolean selectSuperPrev = ((AttrContext) env.info).selectSuper;
        ((AttrContext) env.info).selectSuper = sitesym != null &&
                (sitesym.name == names._super || sitesym.kind == TYP);
        Symbol sym = selectSym(tree, site, env, pt, pkind);
        tree.sym = sym;
        if (sym.kind == VAR) {
            VarSymbol v = (VarSymbol) sym;
            evalInit(v);
            if (pkind == VAR)
                checkAssignable(tree.pos, v, tree.selected, env);
        }
        if (isType(sym) && (sitesym == null || (sitesym.kind & (TYP | PCK)) == 0)) {
            tree.type = check(tree.selected, pt,
                    sitesym == null ? VAL : sitesym.kind, TYP | PCK, pt);
        }
        if (((AttrContext) env.info).selectSuper) {
            if ((sym.flags() & STATIC) == 0 && sym.name != names._this &&
                    sym.name != names._super) {
                if (sitesym.name == names._super) {
                    rs.checkNonAbstract(tree.pos, sym);
                } else if (sym.kind == VAR || sym.kind == MTH) {
                    rs.access(new Resolve.StaticError(sym), tree.pos, site,
                            sym.name, true);
                }
                if (site.isRaw()) {
                    Type site1 = env.enclClass.sym.type.asSuper(site.tsym);
                    if (site1 != null)
                        site = site1;
                }
            }
            if (((AttrContext) env.info).isSelfCall && tree.name == names._this &&
                    site.tsym == env.enclClass.sym) {
                chk.earlyRefError(tree.pos, sym);
            }
        }
        ((AttrContext) env.info).selectSuper = selectSuperPrev;
        result = checkId(tree, site, sym, env, pkind, pt);
        ((AttrContext) env.info).tvars = Type.emptyList;
    }

    /**
      * Determine symbol referenced by a Select expression,
      *
      *  @param tree   The select tree.
      *  @param site   The type of the selected expression,
      *  @param env    The current environment.
      *  @param pt     The current prototype.
      *  @param pkind  The expected kind(s) of the Select expression.
      */
    private Symbol selectSym(Select tree, Type site, Env env, Type pt, int pkind) {
        int pos = tree.pos;
        Name name = tree.name;
        switch (site.tag) {
        case PACKAGE:
            return rs.access(rs.findIdentInPackage(env, site.tsym, name, pkind),
                    pos, site, name, true);

        case ARRAY:

        case CLASS:
            if (pt.tag == METHOD) {
                return rs.resolveQualifiedMethod(pos, env, site, name, pt.argtypes());
            } else if (name == names._this || name == names._super) {
                return rs.resolveSelf(pos, env, site.tsym, name);
            } else if (name == names._class) {
                return new VarSymbol(STATIC | PUBLIC | FINAL, names._class,
                        syms.classType, site.tsym);
            } else {
                return rs.access(rs.findIdentInType(env, site, name, pkind), pos,
                        site, name, true);
            }

        case ERROR:
            return new ErrorType(name, site.tsym).tsym;

        default:
            if (name == names._class) {
                return new VarSymbol(STATIC | PUBLIC | FINAL, names._class,
                        syms.classType, site.tsym);
            } else {
                log.error(pos, "cant.deref", site.toJava());
                return syms.errSymbol;
            }

        }
    }

    /**
      * Determine type of identifier or select expression and check that
      *  (1) the referenced symbol is not deprecated
      *  (2) the symbol's type is safe (@see checkSafe)
      *  (3) if symbol is a variable, check that its type and kind are
      *      compatible with the prototype and protokind.
      *  (4) if symbol is an instance field of a raw type,
      *      which is being assigned to, issue an unchecked warning if its
      *      type changes under erasure.
      *  (5) if symbol is an instance method of a raw type, issue an
      *      unchecked warning if its argument types change under erasure.
      *  If checks succeed:
      *    If symbol is a constant, return its constant type
      *    else if symbol is a method, return its result type
      *    otherwise return its type.
      *  Otherwise return errType.
      *
      *  @param tree       The syntax tree representing the identifier
      *  @param site       If this is a select, the type of the selected
      *                    expression, otherwise the type of the current class.
      *  @param sym        The symbol representing the identifier.
      *  @param env        The current environment.
      *  @param pkind      The set of expected kinds.
      *  @param pt         The expected type.
      */
    Type checkId(Tree tree, Type site, Symbol sym, Env env, int pkind, Type pt) {
        Type owntype;
        switch (sym.kind) {
        case TYP:
            owntype = sym.type;
            if (owntype.tag == CLASS) {
                Type ownOuter = owntype.outer();
                if (ownOuter.tag == CLASS && site != ownOuter) {
                    Type normSite = site;
                    if (normSite.tag == CLASS)
                        normSite = site.asOuterSuper(ownOuter.tsym);
                    if (normSite != ownOuter)
                        owntype = new ClassType(normSite, Type.emptyList,
                                owntype.tsym);
                }
            }
            break;

        case VAR:
            VarSymbol v = (VarSymbol) sym;
            owntype = (sym.owner.kind == TYP && sym.name != names._this &&
                    sym.name != names._super) ? site.memberType(sym) : sym.type;
            if (v.constValue != null && isStaticReference(tree))
                owntype = owntype.constType(v.constValue);
            break;

        case MTH:
            owntype = rs.instantiate(env, site, sym, pt.argtypes());
            if (owntype == null && Type.isDerivedRaw(pt.argtypes()) &&
                    !((AttrContext) env.info).rawArgs) {
                ((AttrContext) env.info).rawArgs = true;
                owntype = rs.instantiate(env, site, sym, pt.argtypes());
                ((AttrContext) env.info).rawArgs = false;
            }
            if (owntype == null) {
                log.error(tree.pos, "internal.error.cant.instantiate",
                        sym.toJava(), site.toJava(), Type.toJavaList(pt.argtypes()));
            }
            break;

        case PCK:

        case ERR:
            owntype = sym.type;
            break;

        default:
            throw new AssertionError("unexpected kind: " + sym.kind +
                    " in tree " + tree);

        }
        if (sym.name != names.init && (sym.flags() & DEPRECATED) != 0 &&
                (((AttrContext) env.info).scope.owner.flags() & DEPRECATED) ==
                0 && sym.outermostClass() !=
                ((AttrContext) env.info).scope.owner.outermostClass())
            chk.warnDeprecated(tree.pos, sym);
        return check(tree, owntype, sym.kind, pkind, pt);
    }

    /**
      * Check that variable is initialized and evaluate the variable's
      *  initializer, if not yet done. Also check that variable is not
      *  referenced before it is defined.
      *  @param tree    The tree making up the variable reference.
      *  @param env     The current environment.
      *  @param v       The variable's symbol.
      */
    private void checkInit(Ident tree, Env env, VarSymbol v) {
        if (v.pos > tree.pos && v.owner.kind == TYP &&
                canOwnInitializer(((AttrContext) env.info).scope.owner) &&
                v.owner == ((AttrContext) env.info).scope.owner.enclClass() &&
                ((v.flags() & STATIC) != 0) == Resolve.isStatic(env) &&
                (env.tree.tag != Tree.ASSIGN ||
                TreeInfo.skipParens(((Assign) env.tree).lhs) != tree))
            log.error(tree.pos, "illegal.forward.ref");
        evalInit(v);
    }

    /**
      * Can the given symbol be the owner of code which forms part
      *  if class initialization? This is the case if the symbol is
      *  a type or field, or if the symbol is the synthetic method.
      *  owning a block.
      */
    private boolean canOwnInitializer(Symbol sym) {
        return (sym.kind & (VAR | TYP)) != 0 ||
                (sym.kind == MTH && (sym.flags() & BLOCK) != 0);
    }

    /**
      * Evaluate a final variable's initializer, unless this has already been
      *  done, and set variable's constant value, if the initializer is
      *  constant.
      */
    public void evalInit(VarSymbol v) {
        if (v.constValue instanceof AttrContextEnv) {
            AttrContextEnv evalEnv = (AttrContextEnv) v.constValue;
            Name prev = log.useSource(evalEnv.toplevel.sourcefile);
            v.constValue = null;
            Type itype = attribExpr(((VarDef) evalEnv.tree).init, evalEnv, v.type);
            if (itype.constValue != null)
                v.constValue = cfolder.coerce(itype, v.type).constValue;
            log.useSource(prev);
        }
    }

    public void visitLiteral(Literal tree) {
        result = check(tree, litType(tree.typetag).constType(tree.value), VAL,
                pkind, pt);
    }

    /**
      * Return the type of a literal with given type tag.
      */
    Type litType(int tag) {
        return (tag == CLASS) ? syms.stringType : syms.typeOfTag[tag];
    }

    public void visitTypeIdent(TypeIdent tree) {
        result = check(tree, syms.typeOfTag[tree.typetag], TYP, pkind, pt);
    }

    public void visitTypeArray(TypeArray tree) {
        Type etype = attribType(tree.elemtype, env);
        result = check(tree, new ArrayType(etype, syms.arrayClass), TYP, pkind, pt);
    }

    public void visitErroneous(Erroneous tree) {
        result = tree.type = syms.errType;
    }

    /**
      * Default visitor method for all other trees.
      */
    public void visitTree(Tree tree) {
        throw new AssertionError();
    }

    /**
      * Main method: attribute class definition associated with given class symbol.
      *  reporting completion failures at the given position.
      *  @param pos The source position at which completion errors are to be
      *             reported.
      *  @param c   The class symbol whose definition will be attributed.
      */
    public void attribClass(int pos, ClassSymbol c) {
        try {
            attribClass(c);
        } catch (CompletionFailure ex) {
            chk.completionError(pos, ex);
        }
    }

    /**
      * Attribute class definition associated with given class symbol.
      *  @param c   The class symbol whose definition will be attributed.
      */
    void attribClass(ClassSymbol c) throws CompletionFailure {
        if (c.type.tag == ERROR)
            return;
        chk.checkNonCyclic(Position.NOPOS, c.type);
        Type st = c.type.supertype();
        if (st.tag == CLASS)
            attribClass((ClassSymbol) st.tsym);
        if (c.owner.kind == TYP && c.owner.type.tag == CLASS)
            attribClass((ClassSymbol) c.owner);
        if ((c.flags_field & UNATTRIBUTED) != 0) {
            c.flags_field &= ~UNATTRIBUTED;
            Env env = (Env) enter.classEnvs.remove(c);
            Name prev = log.useSource(c.sourcefile);
            try {
                attribClassBody(env, c);
            }
            finally { log.useSource(prev);
                    } }
    }

    /**
      * Finish the attribution of a class.
      */
    private void attribClassBody(Env env, ClassSymbol c) {
        ClassDef tree = (ClassDef) env.tree;
        assert c == tree.sym;
        chk.validate(tree.extending);
        chk.validate(tree.implementing);
        if ((c.flags() & (ABSTRACT | INTERFACE)) == 0) {
            if (!retrofit)
                chk.checkAllDefined(tree.pos, c);
        } else
            chk.checkCompatibleSupertypes(tree.pos, c.type);
        tree.type = c.type;
        chk.checkImplementations(tree);
        for (List l = tree.defs; l.nonEmpty(); l = l.tail) {
            attribStat((Tree) l.head, env);
            if (c.owner.kind != PCK &&
                    ((c.flags() & STATIC) == 0 || c.name == names.empty) &&
                    (TreeInfo.flags((Tree) l.head) & (STATIC | INTERFACE)) != 0) {
                Symbol sym = null;
                if (((Tree) l.head).tag == Tree.VARDEF)
                    sym = ((VarDef) l.head).sym;
                if (sym == null || sym.kind != VAR ||
                        ((VarSymbol) sym).constValue == null)
                    log.error(((Tree) l.head).pos, "icls.cant.have.static.decl");
            }
        }
        chk.checkCyclicConstructors(tree);
    }
}

⌨️ 快捷键说明

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