📄 check.java
字号:
} /** Check for cyclic references. Issue an error if the * symbol of the type referred to has a LOCKED flag set. * * @param pos Position to be used for error reporting. * @param t The type referred to. * @returns True if the check completed on all attributed classes */ private boolean checkNonCyclicInternal(DiagnosticPosition pos, Type t) { boolean complete = true; // was the check complete? //- System.err.println("checkNonCyclicInternal("+t+");");//DEBUG Symbol c = t.tsym; if ((c.flags_field & ACYCLIC) != 0) return true; if ((c.flags_field & LOCKED) != 0) { noteCyclic(pos, (ClassSymbol)c); } else if (!c.type.isErroneous()) { try { c.flags_field |= LOCKED; if (c.type.tag == CLASS) { ClassType clazz = (ClassType)c.type; if (clazz.interfaces_field != null) for (List<Type> l=clazz.interfaces_field; l.nonEmpty(); l=l.tail) complete &= checkNonCyclicInternal(pos, l.head); if (clazz.supertype_field != null) { Type st = clazz.supertype_field; if (st != null && st.tag == CLASS) complete &= checkNonCyclicInternal(pos, st); } if (c.owner.kind == TYP) complete &= checkNonCyclicInternal(pos, c.owner.type); } } finally { c.flags_field &= ~LOCKED; } } if (complete) complete = ((c.flags_field & UNATTRIBUTED) == 0) && c.completer == null; if (complete) c.flags_field |= ACYCLIC; return complete; } /** Note that we found an inheritance cycle. */ private void noteCyclic(DiagnosticPosition pos, ClassSymbol c) { log.error(pos, "cyclic.inheritance", c); for (List<Type> l=types.interfaces(c.type); l.nonEmpty(); l=l.tail) l.head = new ErrorType((ClassSymbol)l.head.tsym); Type st = types.supertype(c.type); if (st.tag == CLASS) ((ClassType)c.type).supertype_field = new ErrorType((ClassSymbol)st.tsym); c.type = new ErrorType(c); c.flags_field |= ACYCLIC; } /** Check that all methods which implement some * method conform to the method they implement. * @param tree The class definition whose members are checked. */ void checkImplementations(JCClassDecl tree) { checkImplementations(tree, tree.sym); }//where /** Check that all methods which implement some * method in `ic' conform to the method they implement. */ void checkImplementations(JCClassDecl tree, ClassSymbol ic) { ClassSymbol origin = tree.sym; for (List<Type> l = types.closure(ic.type); l.nonEmpty(); l = l.tail) { ClassSymbol lc = (ClassSymbol)l.head.tsym; if ((allowGenerics || origin != lc) && (lc.flags() & ABSTRACT) != 0) { for (Scope.Entry e=lc.members().elems; e != null; e=e.sibling) { if (e.sym.kind == MTH && (e.sym.flags() & (STATIC|ABSTRACT)) == ABSTRACT) { MethodSymbol absmeth = (MethodSymbol)e.sym; MethodSymbol implmeth = absmeth.implementation(origin, types, false); if (implmeth != null && implmeth != absmeth && (implmeth.owner.flags() & INTERFACE) == (origin.flags() & INTERFACE)) { // don't check if implmeth is in a class, yet // origin is an interface. This case arises only // if implmeth is declared in Object. The reason is // that interfaces really don't inherit from // Object it's just that the compiler represents // things that way. checkOverride(tree, implmeth, absmeth, origin); } } } } } } /** Check that all abstract methods implemented by a class are * mutually compatible. * @param pos Position to be used for error reporting. * @param c The class whose interfaces are checked. */ void checkCompatibleSupertypes(DiagnosticPosition pos, Type c) { List<Type> supertypes = types.interfaces(c); Type supertype = types.supertype(c); if (supertype.tag == CLASS && (supertype.tsym.flags() & ABSTRACT) != 0) supertypes = supertypes.prepend(supertype); for (List<Type> l = supertypes; l.nonEmpty(); l = l.tail) { if (allowGenerics && !l.head.getTypeArguments().isEmpty() && !checkCompatibleAbstracts(pos, l.head, l.head, c)) return; for (List<Type> m = supertypes; m != l; m = m.tail) if (!checkCompatibleAbstracts(pos, l.head, m.head, c)) return; } checkCompatibleConcretes(pos, c); } /** Check that class c does not implement directly or indirectly * the same parameterized interface with two different argument lists. * @param pos Position to be used for error reporting. * @param type The type whose interfaces are checked. */ void checkClassBounds(DiagnosticPosition pos, Type type) { checkClassBounds(pos, new HashMap<TypeSymbol,Type>(), type); }//where /** Enter all interfaces of type `type' into the hash table `seensofar' * with their class symbol as key and their type as value. Make * sure no class is entered with two different types. */ void checkClassBounds(DiagnosticPosition pos, Map<TypeSymbol,Type> seensofar, Type type) { if (type.isErroneous()) return; for (List<Type> l = types.interfaces(type); l.nonEmpty(); l = l.tail) { Type it = l.head; Type oldit = seensofar.put(it.tsym, it); if (oldit != null) { List<Type> oldparams = oldit.allparams(); List<Type> newparams = it.allparams(); if (!types.containsTypeEquivalent(oldparams, newparams)) log.error(pos, "cant.inherit.diff.arg", it.tsym, Type.toString(oldparams), Type.toString(newparams)); } checkClassBounds(pos, seensofar, it); } Type st = types.supertype(type); if (st != null) checkClassBounds(pos, seensofar, st); } /** Enter interface into into set. * If it existed already, issue a "repeated interface" error. */ void checkNotRepeated(DiagnosticPosition pos, Type it, Set<Type> its) { if (its.contains(it)) log.error(pos, "repeated.interface"); else { its.add(it); } } /* ************************************************************************* * Check annotations **************************************************************************/ /** Annotation types are restricted to primitives, String, an * enum, an annotation, Class, Class<?>, Class<? extends * Anything>, arrays of the preceding. */ void validateAnnotationType(JCTree restype) { // restype may be null if an error occurred, so don't bother validating it if (restype != null) { validateAnnotationType(restype.pos(), restype.type); } } void validateAnnotationType(DiagnosticPosition pos, Type type) { if (type.isPrimitive()) return; if (types.isSameType(type, syms.stringType)) return; if ((type.tsym.flags() & Flags.ENUM) != 0) return; if ((type.tsym.flags() & Flags.ANNOTATION) != 0) return; if (types.lowerBound(type).tsym == syms.classType.tsym) return; if (types.isArray(type) && !types.isArray(types.elemtype(type))) { validateAnnotationType(pos, types.elemtype(type)); return; } log.error(pos, "invalid.annotation.member.type"); } /** * "It is also a compile-time error if any method declared in an * annotation type has a signature that is override-equivalent to * that of any public or protected method declared in class Object * or in the interface annotation.Annotation." * * @jls3 9.6 Annotation Types */ void validateAnnotationMethod(DiagnosticPosition pos, MethodSymbol m) { for (Type sup = syms.annotationType; sup.tag == CLASS; sup = types.supertype(sup)) { Scope s = sup.tsym.members(); for (Scope.Entry e = s.lookup(m.name); e.scope != null; e = e.next()) { if (e.sym.kind == MTH && (e.sym.flags() & (PUBLIC | PROTECTED)) != 0 && types.overrideEquivalent(m.type, e.sym.type)) log.error(pos, "intf.annotation.member.clash", e.sym, sup); } } } /** Check the annotations of a symbol. */ public void validateAnnotations(List<JCAnnotation> annotations, Symbol s) { if (skipAnnotations) return; for (JCAnnotation a : annotations) validateAnnotation(a, s); } /** Check an annotation of a symbol. */ public void validateAnnotation(JCAnnotation a, Symbol s) { validateAnnotation(a); if (!annotationApplicable(a, s)) log.error(a.pos(), "annotation.type.not.applicable"); if (a.annotationType.type.tsym == syms.overrideType.tsym) { if (!isOverrider(s)) log.error(a.pos(), "method.does.not.override.superclass"); } } /** Is s a method symbol that overrides a method in a superclass? */ boolean isOverrider(Symbol s) { if (s.kind != MTH || s.isStatic()) return false; MethodSymbol m = (MethodSymbol)s; TypeSymbol owner = (TypeSymbol)m.owner; for (Type sup : types.closure(owner.type)) { if (sup == owner.type) continue; // skip "this" Scope scope = sup.tsym.members(); for (Scope.Entry e = scope.lookup(m.name); e.scope != null; e = e.next()) { if (!e.sym.isStatic() && m.overrides(e.sym, owner, types, true)) return true; } } return false; } /** Is the annotation applicable to the symbol? */ boolean annotationApplicable(JCAnnotation a, Symbol s) { Attribute.Compound atTarget = a.annotationType.type.tsym.attribute(syms.annotationTargetType.tsym); if (atTarget == null) return true; Attribute atValue = atTarget.member(names.value); if (!(atValue instanceof Attribute.Array)) return true; // error recovery Attribute.Array arr = (Attribute.Array) atValue; for (Attribute app : arr.values) { if (!(app instanceof Attribute.Enum)) return true; // recovery Attribute.Enum e = (Attribute.Enum) app; if (e.value.name == names.TYPE) { if (s.kind == TYP) return true; } else if (e.value.name == names.FIELD) { if (s.kind == VAR && s.owner.kind != MTH) return true; } else if (e.value.name == names.METHOD) { if (s.kind == MTH && !s.isConstructor()) return true; } else if (e.value.name == names.PARAMETER) { if (s.kind == VAR && s.owner.kind == MTH && (s.flags() & PARAMETER) != 0) return true; } else if (e.value.name == names.CONSTRUCTOR) { if (s.kind == MTH && s.isConstructor()) return true; } else if (e.value.name == names.LOCAL_VARIABLE) { if (s.kind == VAR && s.owner.kind == MTH && (s.flags() & PARAMETER) == 0) return true; } else if (e.value.name == names.ANNOTATION_TYPE) { if (s.kind == TYP && (s.flags() & ANNOTATION) != 0) return true; } else if (e.value.name == names.PACKAGE) { if (s.kind == PCK) return true; } else return true; // recovery } return false; } /** Check an annotation value. */ public void validateAnnotation(JCAnnotation a) { if (a.type.isErroneous()) return; // collect an inventory of the members Set<MethodSymbol> members = new HashSet<MethodSymbol>(); for (Scope.Entry e = a.annotationType.type.tsym.members().elems; e != null; e = e.sibling) if (e.sym.kind == MTH) members.add((MethodSymbol) e.sym); // count them off as they're annotated for (JCTree arg : a.args) { if (arg.getTag() != JCTree.ASSIGN) continue; // recovery JCAssign assign = (JCAssign) arg; Symbol m = TreeInfo.symbol(assign.lhs); if (m == null || m.type.isErroneous()) continue; if (!members.remove(m)) log.error(arg.pos(), "duplicate.annotation.member.value", m.name, a.type); if (assign.rhs.getTag() == ANNOTATION) validateAnnotation((JCAnnotation)assign.rhs); } // all the remaining ones better have default values for (MethodSymbol m : members) if (m.defaultValue == null && !m.type.isErroneous()) log.error(a.pos(), "annotation.missing.default.value", a.type, m.name); // special case: java.lang.annotation.Target must not have // repeated values in its value member if (a.annotationType.type.tsym != syms.annotationTargetType.tsym || a.args.tail == null) return; if (a.args.head.getTag() != JCTree.ASSIGN) return; // error recovery JCAssign assign = (JCAssign) a.args.head; Symbol m = TreeInfo.symbol(assign.lhs); if (m.name != names.value) return; JCTree rhs = assign.rhs; if (rhs.getTag() != JCTree.NEWARRAY) return; JCNewArray na = (JCNewArray) rhs; Set<Symbol> targets = new HashSet<Symbol>(); for (JCTree elem : na.elems) { if (!targets.add(TreeInfo.symbol(elem))) { log.error(elem.pos(), "repeated.annotation.target"); } } } void checkDeprecatedAnnotation(DiagnosticPosition pos, Symbol s) { if (allowAnnotations && lint.isEnabled(Lint.LintCategory.DEP_ANN) && (s.flags() & DEPRECATED) != 0 && !syms.deprecatedType.isErroneous() && s.attribute(syms.deprecatedType.tsym) == null) { log.warning(pos, "missing.deprecated.annotation"); } }/* ************************************************************************* * Check for recursive annotation elements. **************************************************************************/ /** Check for cycles in the graph of annotation elements. */ void checkNonCyclicElements(JCClassDecl tree) { if ((tree.sym.flags_field & ANNOTATION) == 0) return; assert (tree.sym.flags_field & LOCKED) == 0; try { tree.sym.flags_field |= LOCKED; for (JCTree def : tree.defs) { if (def.getTag() != JCTree.METHODDEF) continue; JCMethodDecl meth = (JCMethodDecl)def; checkAnnotationResType(meth.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -