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