attr.java

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

JAVA
1,568
字号
            attribStat(stmt, env);        } catch (BreakAttr b) {            return b.env;        } finally {            breakTree = null;            log.useSource(prev);        }        return env;    }        private JCTree breakTree = null;        private static class BreakAttr extends RuntimeException {        static final long serialVersionUID = -6924771130405446405L;        private Env<AttrContext> env;        private BreakAttr(Env<AttrContext> env) {            this.env = env;        }    }   /* ************************************************************************ * Visitor methods *************************************************************************/    /** Visitor argument: the current environment.     */    Env<AttrContext> env;    /** Visitor argument: the currently expected proto-kind.     */    int pkind;    /** Visitor argument: the currently expected proto-type.     */    Type pt;    /** Visitor result: the computed type.     */    Type result;    /** Visitor method: attribute a tree, catching any completion failure     *  exceptions. Return the tree's type.     *     *  @param tree    The tree to be visited.     *  @param env     The environment visitor argument.     *  @param pkind   The protokind visitor argument.     *  @param pt      The prototype visitor argument.     */    Type attribTree(JCTree tree, Env<AttrContext> env, int pkind, Type pt) {        Env<AttrContext> prevEnv = this.env;        int prevPkind = this.pkind;        Type prevPt = this.pt;        try {            this.env = env;            this.pkind = pkind;            this.pt = pt;            tree.accept(this);            if (tree == breakTree)                throw new BreakAttr(env);            return result;        } catch (CompletionFailure ex) {            tree.type = syms.errType;            return chk.completionError(tree.pos(), ex);        } finally {            this.env = prevEnv;            this.pkind = prevPkind;            this.pt = prevPt;        }    }    /** Derived visitor method: attribute an expression tree.     */    public Type attribExpr(JCTree tree, Env<AttrContext> env, Type pt) {        return attribTree(tree, env, VAL, pt.tag != ERROR ? pt : Type.noType);    }    /** Derived visitor method: attribute an expression tree with     *  no constraints on the computed type.     */    Type attribExpr(JCTree tree, Env<AttrContext> env) {        return attribTree(tree, env, VAL, Type.noType);    }    /** Derived visitor method: attribute a type tree.     */    Type attribType(JCTree tree, Env<AttrContext> env) {        Type result = attribTree(tree, env, TYP, Type.noType);        return result;    }    /** Derived visitor method: attribute a statement or definition tree.     */    public Type attribStat(JCTree tree, Env<AttrContext> env) {        return attribTree(tree, env, NIL, Type.noType);    }    /** Attribute a list of expressions, returning a list of types.     */    List<Type> attribExprs(List<JCExpression> trees, Env<AttrContext> env, Type pt) {        ListBuffer<Type> ts = new ListBuffer<Type>();        for (List<JCExpression> l = trees; l.nonEmpty(); l = l.tail)            ts.append(attribExpr(l.head, env, pt));        return ts.toList();    }    /** Attribute a list of statements, returning nothing.     */    <T extends JCTree> void attribStats(List<T> trees, Env<AttrContext> env) {        for (List<T> l = trees; l.nonEmpty(); l = l.tail)            attribStat(l.head, env);    }    /** Attribute the arguments in a method call, returning a list of types.     */    List<Type> attribArgs(List<JCExpression> trees, Env<AttrContext> env) {        ListBuffer<Type> argtypes = new ListBuffer<Type>();        for (List<JCExpression> l = trees; l.nonEmpty(); l = l.tail)            argtypes.append(chk.checkNonVoid(                l.head.pos(), types.upperBound(attribTree(l.head, env, VAL, Infer.anyPoly))));        return argtypes.toList();    }    /** Attribute a type argument list, returning a list of types.     */    List<Type> attribTypes(List<JCExpression> trees, Env<AttrContext> env) {        ListBuffer<Type> argtypes = new ListBuffer<Type>();        for (List<JCExpression> l = trees; l.nonEmpty(); l = l.tail)            argtypes.append(chk.checkRefType(l.head.pos(), attribType(l.head, env)));        return argtypes.toList();    }    /**     * Attribute type variables (of generic classes or methods).     * Compound types are attributed later in attribBounds.     * @param typarams the type variables to enter     * @param env      the current environment     */    void attribTypeVariables(List<JCTypeParameter> typarams, Env<AttrContext> env) {        for (JCTypeParameter tvar : typarams) {            TypeVar a = (TypeVar)tvar.type;            if (!tvar.bounds.isEmpty()) {                List<Type> bounds = List.of(attribType(tvar.bounds.head, env));                for (JCExpression bound : tvar.bounds.tail)                    bounds = bounds.prepend(attribType(bound, env));                types.setBounds(a, bounds.reverse());            } else {                // if no bounds are given, assume a single bound of                // java.lang.Object.                types.setBounds(a, List.of(syms.objectType));            }        }        for (JCTypeParameter tvar : typarams)            chk.checkNonCyclic(tvar.pos(), (TypeVar)tvar.type);        attribStats(typarams, env);    }    void attribBounds(List<JCTypeParameter> typarams) {        for (JCTypeParameter typaram : typarams) {            Type bound = typaram.type.getUpperBound();            if (bound != null && bound.tsym instanceof ClassSymbol) {                ClassSymbol c = (ClassSymbol)bound.tsym;                if ((c.flags_field & COMPOUND) != 0) {                    assert (c.flags_field & UNATTRIBUTED) != 0 : c;                    attribClass(typaram.pos(), c);                }            }        }    }    /**     * Attribute the type references in a list of annotations.     */    void attribAnnotationTypes(List<JCAnnotation> annotations,                               Env<AttrContext> env) {        for (List<JCAnnotation> al = annotations; al.nonEmpty(); al = al.tail) {            JCAnnotation a = al.head;            attribType(a.annotationType, env);        }    }    /** Attribute type reference in an `extends' or `implements' clause.     *     *  @param tree              The tree making up the type reference.     *  @param env               The environment current at the reference.     *  @param classExpected     true if only a class is expected here.     *  @param interfaceExpected true if only an interface is expected here.     */    Type attribBase(JCTree tree,                    Env<AttrContext> env,                    boolean classExpected,                    boolean interfaceExpected,                    boolean checkExtensible) {        Type t = attribType(tree, env);        return checkBase(t, tree, env, classExpected, interfaceExpected, checkExtensible);    }    Type checkBase(Type t,                   JCTree tree,                   Env<AttrContext> env,                   boolean classExpected,                   boolean interfaceExpected,                   boolean checkExtensible) {        if (t.tag == TYPEVAR && !classExpected && !interfaceExpected) {            // check that type variable is already visible            if (t.getUpperBound() == null) {                log.error(tree.pos(), "illegal.forward.ref");                return syms.errType;            }        } else {            t = chk.checkClassType(tree.pos(), t, checkExtensible|!allowGenerics);        }        if (interfaceExpected && (t.tsym.flags() & INTERFACE) == 0) {            log.error(tree.pos(), "intf.expected.here");            // return errType is necessary since otherwise there might            // be undetected cycles which cause attribution to loop            return syms.errType;        } else if (checkExtensible &&                   classExpected &&                   (t.tsym.flags() & INTERFACE) != 0) {            log.error(tree.pos(), "no.intf.expected.here");            return syms.errType;        }        if (checkExtensible &&            ((t.tsym.flags() & FINAL) != 0)) {            log.error(tree.pos(),                      "cant.inherit.from.final", t.tsym);        }        chk.checkNonCyclic(tree.pos(), t);        return t;    }    public void visitClassDef(JCClassDecl tree) {        // Local classes have not been entered yet, so we need to do it now:        if ((env.info.scope.owner.kind & (VAR | MTH)) != 0)            enter.classEnter(tree, env);        ClassSymbol c = tree.sym;        if (c == null) {            // exit in case something drastic went wrong during enter.            result = null;        } else {            // make sure class has been completed:            c.complete();            // If this class appears as an anonymous class            // in a superclass constructor call where            // no explicit outer instance is given,            // disable implicit outer instance from being passed.            // (This would be an illegal access to "this before super").            if (env.info.isSelfCall &&                env.tree.getTag() == JCTree.NEWCLASS &&                ((JCNewClass) env.tree).encl == null)            {                c.flags_field |= NOOUTERTHIS;            }            attribClass(tree.pos(), c);            result = tree.type = c.type;        }    }    public void visitMethodDef(JCMethodDecl tree) {        MethodSymbol m = tree.sym;        Lint lint = env.info.lint.augment(m.attributes_field, m.flags());        Lint prevLint = chk.setLint(lint);        try {            chk.checkDeprecatedAnnotation(tree.pos(), m);            attribBounds(tree.typarams);            // If we override any other methods, check that we do so properly.            // JLS ???            chk.checkOverride(tree, m);            // Create a new environment with local scope            // for attributing the method.            Env<AttrContext> localEnv = memberEnter.methodEnv(tree, env);            localEnv.info.lint = lint;            // Enter all type parameters into the local method scope.            for (List<JCTypeParameter> l = tree.typarams; l.nonEmpty(); l = l.tail)                localEnv.info.scope.enterIfAbsent(l.head.type.tsym);            ClassSymbol owner = env.enclClass.sym;            if ((owner.flags() & ANNOTATION) != 0 &&                tree.params.nonEmpty())                log.error(tree.params.head.pos(),                          "intf.annotation.members.cant.have.params");            // Attribute all value parameters.            for (List<JCVariableDecl> l = tree.params; l.nonEmpty(); l = l.tail) {                attribStat(l.head, localEnv);            }            // Check that type parameters are well-formed.            chk.validateTypeParams(tree.typarams);            if ((owner.flags() & ANNOTATION) != 0 &&                tree.typarams.nonEmpty())                log.error(tree.typarams.head.pos(),                          "intf.annotation.members.cant.have.type.params");            // Check that result type is well-formed.            chk.validate(tree.restype);            if ((owner.flags() & ANNOTATION) != 0)                chk.validateAnnotationType(tree.restype);            if ((owner.flags() & ANNOTATION) != 0)                chk.validateAnnotationMethod(tree.pos(), m);            // Check that all exceptions mentioned in the throws clause extend            // java.lang.Throwable.            if ((owner.flags() & ANNOTATION) != 0 && tree.thrown.nonEmpty())

⌨️ 快捷键说明

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