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 + -
显示快捷键?