attr.java

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

JAVA
1,568
字号
                log.error(tree.thrown.head.pos(),                          "throws.not.allowed.in.intf.annotation");            for (List<JCExpression> l = tree.thrown; l.nonEmpty(); l = l.tail)                chk.checkType(l.head.pos(), l.head.type, syms.throwableType);            if (tree.body == null) {                // Empty bodies are only allowed for                // abstract, native, or interface methods, or for methods                // in a retrofit signature class.                if ((owner.flags() & INTERFACE) == 0 &&                    (tree.mods.flags & (ABSTRACT | NATIVE)) == 0 &&                    !relax)                    log.error(tree.pos(), "missing.meth.body.or.decl.abstract");                if (tree.defaultValue != null) {                    if ((owner.flags() & ANNOTATION) == 0)                        log.error(tree.pos(),                                  "default.allowed.in.intf.annotation.member");                }            } else if ((owner.flags() & INTERFACE) != 0) {                log.error(tree.body.pos(), "intf.meth.cant.have.body");            } else if ((tree.mods.flags & ABSTRACT) != 0) {                log.error(tree.pos(), "abstract.meth.cant.have.body");            } else if ((tree.mods.flags & NATIVE) != 0) {                log.error(tree.pos(), "native.meth.cant.have.body");            } else {                // Add an implicit super() call unless an explicit call to                // super(...) or this(...) is given                // or we are compiling class java.lang.Object.                if (tree.name == names.init && owner.type != syms.objectType) {                    JCBlock body = tree.body;                    if (body.stats.isEmpty() ||                        !TreeInfo.isSelfCall(body.stats.head)) {                        body.stats = body.stats.                            prepend(memberEnter.SuperCall(make.at(body.pos),                                                          List.<Type>nil(),                                                          List.<JCVariableDecl>nil(),                                                          false));                    } else if ((env.enclClass.sym.flags() & ENUM) != 0 &&                               (tree.mods.flags & GENERATEDCONSTR) == 0 &&                               TreeInfo.isSuperCall(body.stats.head)) {                        // enum constructors are not allowed to call super                        // directly, so make sure there aren't any super calls                        // in enum constructors, except in the compiler                        // generated one.                        log.error(tree.body.stats.head.pos(),                                  "call.to.super.not.allowed.in.enum.ctor",                                  env.enclClass.sym);                    }                }                // Attribute method body.                attribStat(tree.body, localEnv);            }            localEnv.info.scope.leave();            result = tree.type = m.type;            chk.validateAnnotations(tree.mods.annotations, m);        }        finally {            chk.setLint(prevLint);        }    }    public void visitVarDef(JCVariableDecl tree) {        // Local variables have not been entered yet, so we need to do it now:        if (env.info.scope.owner.kind == MTH) {            if (tree.sym != null) {                // parameters have already been entered                env.info.scope.enter(tree.sym);            } else {                memberEnter.memberEnter(tree, env);                annotate.flush();            }        }        // Check that the variable's declared type is well-formed.        chk.validate(tree.vartype);        VarSymbol v = tree.sym;        Lint lint = env.info.lint.augment(v.attributes_field, v.flags());        Lint prevLint = chk.setLint(lint);        try {            chk.checkDeprecatedAnnotation(tree.pos(), v);            if (tree.init != null) {                if ((v.flags_field & FINAL) != 0 && tree.init.getTag() != JCTree.NEWCLASS) {                    // In this case, `v' is final.  Ensure that it's initializer is                    // evaluated.                    v.getConstValue(); // ensure initializer is evaluated                } else {                    // Attribute initializer in a new environment                    // with the declared variable as owner.                    // Check that initializer conforms to variable's declared type.                    Env<AttrContext> initEnv = memberEnter.initEnv(tree, env);                    initEnv.info.lint = lint;                    // In order to catch self-references, we set the variable's                    // declaration position to maximal possible value, effectively                    // marking the variable as undefined.                    v.pos = Position.MAXPOS;                    attribExpr(tree.init, initEnv, v.type);                    v.pos = tree.pos;                }            }            result = tree.type = v.type;            chk.validateAnnotations(tree.mods.annotations, v);        }        finally {            chk.setLint(prevLint);        }    }    public void visitSkip(JCSkip tree) {        result = null;    }    public void visitBlock(JCBlock tree) {        if (env.info.scope.owner.kind == TYP) {            // Block is a static or instance initializer;            // let the owner of the environment be a freshly            // created BLOCK-method.            Env<AttrContext> localEnv =                env.dup(tree, env.info.dup(env.info.scope.dupUnshared()));            localEnv.info.scope.owner =                new MethodSymbol(tree.flags | BLOCK, names.empty, null,                                 env.info.scope.owner);            if ((tree.flags & STATIC) != 0) localEnv.info.staticLevel++;            attribStats(tree.stats, localEnv);        } else {            // Create a new local environment with a local scope.            Env<AttrContext> localEnv =                env.dup(tree, env.info.dup(env.info.scope.dup()));            attribStats(tree.stats, localEnv);            localEnv.info.scope.leave();        }        result = null;    }    public void visitDoLoop(JCDoWhileLoop tree) {        attribStat(tree.body, env.dup(tree));        attribExpr(tree.cond, env, syms.booleanType);        result = null;    }    public void visitWhileLoop(JCWhileLoop tree) {        attribExpr(tree.cond, env, syms.booleanType);        attribStat(tree.body, env.dup(tree));        result = null;    }    public void visitForLoop(JCForLoop tree) {        Env<AttrContext> loopEnv =            env.dup(env.tree, env.info.dup(env.info.scope.dup()));        attribStats(tree.init, loopEnv);        if (tree.cond != null) attribExpr(tree.cond, loopEnv, syms.booleanType);        loopEnv.tree = tree; // before, we were not in loop!        attribStats(tree.step, loopEnv);        attribStat(tree.body, loopEnv);        loopEnv.info.scope.leave();        result = null;    }    public void visitForeachLoop(JCEnhancedForLoop tree) {        Env<AttrContext> loopEnv =            env.dup(env.tree, env.info.dup(env.info.scope.dup()));        attribStat(tree.var, loopEnv);        Type exprType = types.upperBound(attribExpr(tree.expr, loopEnv));        chk.checkNonVoid(tree.pos(), exprType);        Type elemtype = types.elemtype(exprType); // perhaps expr is an array?        if (elemtype == null) {            // or perhaps expr implements Iterable<T>?            Type base = types.asSuper(exprType, syms.iterableType.tsym);            if (base == null) {                log.error(tree.expr.pos(), "foreach.not.applicable.to.type");                elemtype = syms.errType;            } else {                List<Type> iterableParams = base.allparams();                elemtype = iterableParams.isEmpty()                    ? syms.objectType                    : types.upperBound(iterableParams.head);            }        }        chk.checkType(tree.expr.pos(), elemtype, tree.var.sym.type);        loopEnv.tree = tree; // before, we were not in loop!        attribStat(tree.body, loopEnv);        loopEnv.info.scope.leave();        result = null;    }    public void visitLabelled(JCLabeledStatement tree) {        // Check that label is not used in an enclosing statement        Env<AttrContext> env1 = env;        while (env1 != null && env1.tree.getTag() != JCTree.CLASSDEF) {            if (env1.tree.getTag() == JCTree.LABELLED &&                ((JCLabeledStatement) env1.tree).label == tree.label) {                log.error(tree.pos(), "label.already.in.use",                          tree.label);                break;            }            env1 = env1.next;        }        attribStat(tree.body, env.dup(tree));        result = null;    }    public void visitSwitch(JCSwitch tree) {        Type seltype = attribExpr(tree.selector, env);        Env<AttrContext> switchEnv =            env.dup(tree, env.info.dup(env.info.scope.dup()));        boolean enumSwitch =            allowEnums &&            (seltype.tsym.flags() & Flags.ENUM) != 0;        if (!enumSwitch)            seltype = chk.checkType(tree.selector.pos(), seltype, syms.intType);        // Attribute all cases and        // check that there are no duplicate case labels or default clauses.        Set<Object> labels = new HashSet<Object>(); // The set of case labels.        boolean hasDefault = false;      // Is there a default label?        for (List<JCCase> l = tree.cases; l.nonEmpty(); l = l.tail) {            JCCase c = l.head;            Env<AttrContext> caseEnv =                switchEnv.dup(c, env.info.dup(switchEnv.info.scope.dup()));            if (c.pat != null) {                if (enumSwitch) {                    Symbol sym = enumConstant(c.pat, seltype);                    if (sym == null) {                        log.error(c.pat.pos(), "enum.const.req");                    } else if (!labels.add(sym)) {                        log.error(c.pos(), "duplicate.case.label");                    }                } else {                    Type pattype = attribExpr(c.pat, switchEnv, seltype);                    if (pattype.tag != ERROR) {                        if (pattype.constValue() == null) {                            log.error(c.pat.pos(), "const.expr.req");                        } else if (labels.contains(pattype.constValue())) {                            log.error(c.pos(), "duplicate.case.label");                        } else {                            labels.add(pattype.constValue());                        }                    }                }            } else if (hasDefault) {                log.error(c.pos(), "duplicate.default.label");            } else {                hasDefault = true;            }            attribStats(c.stats, caseEnv);            caseEnv.info.scope.leave();            addVars(c.stats, switchEnv.info.scope);        }        switchEnv.info.scope.leave();        result = null;    }    // where        /** Add any variables defined in stats to the switch scope. */        private static void addVars(List<JCStatement> stats, Scope switchScope) {            for (;stats.nonEmpty(); stats = stats.tail) {                JCTree stat = stats.head;                if (stat.getTag() == JCTree.VARDEF)                    switchScope.enter(((JCVariableDecl) stat).sym);            }        }    // where    /** Return the selected enumeration constant symbol, or null. */    private Symbol enumConstant(JCTree tree, Type enumType) {        if (tree.getTag() != JCTree.IDENT) {            log.error(tree.pos(), "enum.label.must.be.unqualified.enum");            return syms.errSymbol;        }        JCIdent ident = (JCIdent)tree;        Name name = ident.name;        for (Scope.Entry e = enumType.tsym.members().lookup(name);             e.scope != null; e = e.next()) {            if (e.sym.kind == VAR) {                Symbol s = ident.sym = e.sym;                ((VarSymbol)s).getConstValue(); // ensure initializer is evaluated                ident.type = s.type;                return ((s.flags_field & Flags.ENUM) == 0)                    ? null : s;            }        }        return null;    }    public void visitSynchronized(JCSynchronized tree) {        chk.checkRefType(tree.pos(), attribExpr(tree.lock, env));        attribStat(tree.body, env);        result = null;    }    public void visitTry(JCTry tree) {        // Attribute body        attribStat(tree.body, env.dup(tree, env.info.dup()));        // Attribute catch clauses        for (List<JCCatch> l = tree.catchers; l.nonEmpty(); l = l.tail) {            JCCatch c = l.head;            Env<AttrContext> catchEnv =                env.dup(c, env.info.dup(env.info.scope.dup()));            Type ctype = attribStat(c.param, catchEnv);            if (c.param.type.tsym.kind == Kinds.VAR) {                c.param.sym.setData(ElementKind.EXCEPTION_PARAMETER);            }            chk.checkType(c.param.vartype.pos(),                          chk.checkClassType(c.param.vartype.pos(), ctype),                          syms.throwableType);            attribStat(c.body, catchEnv);            catchEnv.info.scope.leave();

⌨️ 快捷键说明

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