📄 check.java
字号:
mask = MethodFlags; } if (((flags | implicit) & Flags.ABSTRACT) == 0) implicit |= sym.owner.flags_field & STRICTFP; break; case TYP: if (sym.isLocal()) { mask = LocalClassFlags; if (sym.name.len == 0) mask |= STATIC; } else if (sym.owner.kind == TYP) { mask = MemberClassFlags; if (sym.owner.owner.kind == PCK || (sym.owner.flags_field & STATIC) != 0) mask |= STATIC; if ((flags & INTERFACE) != 0) implicit = STATIC; } else { mask = ClassFlags; } if ((flags & INTERFACE) != 0) implicit |= ABSTRACT; implicit |= sym.owner.flags_field & STRICTFP; break; default: throw new AssertionError(); } long illegal = flags & StandardFlags & ~mask; if (illegal != 0) log.error(pos, "mod.not.allowed.here", TreeInfo.flagNames(illegal)); else if ( (sym.kind == TYP || checkDisjoint(pos, flags, ABSTRACT, PRIVATE | STATIC)) && checkDisjoint(pos, flags, ABSTRACT | INTERFACE, FINAL | NATIVE | SYNCHRONIZED) && checkDisjoint(pos, flags, PUBLIC, PRIVATE | PROTECTED) && checkDisjoint(pos, flags, PRIVATE, PUBLIC | PROTECTED) && checkDisjoint(pos, flags, FINAL, VOLATILE) && (sym.kind == TYP || checkDisjoint(pos, flags, ABSTRACT | NATIVE, STRICTFP))) { } return flags & (mask | ~StandardFlags) | implicit; } /** * Validate a type expression. That is, * check that all type arguments of a parametric type are within * their bounds. This must be done in a second phase after type attributon * since a class might have a subclass as type parameter bound. E.g: * * class B<A extends C> { ... } * class C extends B<C> { ... } * * and we can't make sure that the bound is already attributed because * of possible cycles. */ private Validator validator = new Validator(); /** * Visitor method: Validate a type expression, if it is not null, catching * and reporting any completion failures. */ void validate(Tree tree) { try { if (tree != null) tree.accept(validator); } catch (CompletionFailure ex) { completionError(tree.pos, ex); } } /** * Visitor method: Validate a list of type expressions. */ void validate(List trees) { for (List l = trees; l.nonEmpty(); l = l.tail) validate((Tree) l.head); } /** * A visitor class for type validation. */ class Validator extends Visitor { Validator() { super(); } public void visitTypeArray(TypeArray tree) { validate(tree.elemtype); } public void visitSelect(Select tree) { if (tree.type.tag == CLASS) { if (tree.type.outer().tag == CLASS) validate(tree.selected); else if (tree.selected.type.isParameterized()) log.error(tree.pos, "cant.select.static.class.from.param.type"); if (tree.type.isRaw() && tree.type.allparams().nonEmpty()) log.error(tree.pos, "improperly.formed.type.param.missing"); } } /** * Default visitor method: do nothing. */ public void visitTree(Tree tree) { } } /** * Is given type a subtype of some of the types in given list? */ static boolean subset(Type t, List ts) { for (List l = ts; l.nonEmpty(); l = l.tail) if (t.isSubType((Type) l.head)) return true; return false; } /** * Is given type a subtype or supertype of * some of the types in given list? */ static boolean intersects(Type t, List ts) { for (List l = ts; l.nonEmpty(); l = l.tail) if (t.isSubType((Type) l.head) || ((Type) l.head).isSubType(t)) return true; return false; } /** * Add type set to given type list, unless it is a subclass of some class * in the list. */ static List incl(Type t, List ts) { return subset(t, ts) ? ts : excl(t, ts).prepend(t); } /** * Remove type set from type set list. */ static List excl(Type t, List ts) { if (ts.isEmpty()) { return ts; } else { List ts1 = excl(t, ts.tail); if (((Type) ts.head).isSubType(t)) return ts1; else if (ts1 == ts.tail) return ts; else return ts1.prepend(ts.head); } } /** * Form the union of two type set lists. */ static List union(List ts1, List ts2) { List ts = ts1; for (List l = ts2; l.nonEmpty(); l = l.tail) ts = incl((Type) l.head, ts); return ts; } /** * Form the difference of two type lists. */ static List diff(List ts1, List ts2) { List ts = ts1; for (List l = ts2; l.nonEmpty(); l = l.tail) ts = excl((Type) l.head, ts); return ts; } /** * Form the intersection of two type lists. */ static List intersect(List ts1, List ts2) { List ts = Type.emptyList; for (List l = ts1; l.nonEmpty(); l = l.tail) if (subset((Type) l.head, ts2)) ts = incl((Type) l.head, ts); for (List l = ts2; l.nonEmpty(); l = l.tail) if (subset((Type) l.head, ts1)) ts = incl((Type) l.head, ts); return ts; } /** * Is exc an exception symbol that need not be declared? */ boolean isUnchecked(ClassSymbol exc) { return exc.kind == ERR || exc.isSubClass(syms.errorType.tsym) || exc.isSubClass(syms.runtimeExceptionType.tsym); } /** * Is exc an exception type that need not be declared? */ boolean isUnchecked(Type exc) { return (exc.tag == CLASS) ? isUnchecked((ClassSymbol) exc.tsym) : false; } /** * Same, but handling completion failures. */ boolean isUnchecked(int pos, Type exc) { try { return isUnchecked(exc); } catch (CompletionFailure ex) { completionError(pos, ex); return true; } } /** * Is exc handled by given exception list? */ boolean isHandled(Type exc, List handled) { return isUnchecked(exc) || subset(exc, handled); } /** * Return all exceptions in thrown list that are not in handled list. * @param thrown The list of thrown exceptions. * @param handled The list of handled exceptions. */ List unHandled(List thrown, List handled) { List unhandled = Type.emptyList; for (List l = thrown; l.nonEmpty(); l = l.tail) if (!isHandled((Type) l.head, handled)) unhandled = unhandled.prepend(l.head); return unhandled; } /** * The level of access protection given by a flag set, * where PRIVATE is highest and PUBLIC is lowest. */ static int protection(long flags) { switch ((short)(flags & AccessFlags)) { case PRIVATE: return 3; case PROTECTED: return 1; case PUBLIC: return 0; default: return 2; } } /** * A string describing the access permission given by a flag set. * This always returns a space-separated list of Java Keywords. */ private static String protectionString(long flags) { long flags1 = flags & AccessFlags; return (flags1 == 0) ? "package" : TreeInfo.flagNames(flags1); } /** * A customized "cannot override" error message. * @param m The overriding method. * @param other The overridden method. * @return An internationalized string. */ static String cannotOverride(MethodSymbol m, MethodSymbol other) { String msg; if ((other.owner.flags() & INTERFACE) == 0) msg = Log.getLocalizedString("cant.override", m.toJava(), m.javaLocation(), other.toJava(), other.javaLocation()); else if ((m.owner.flags() & INTERFACE) == 0) msg = Log.getLocalizedString("cant.implement", m.toJava(), m.javaLocation(), other.toJava(), other.javaLocation()); else msg = Log.getLocalizedString("clashes.with", m.toJava(), m.javaLocation(), other.toJava(), other.javaLocation()); return msg; } /** * Check that this method conforms with overridden method 'other'. * where `origin' is the class where checking started. * Complications: * (1) Do not check overriding of synthetic methods * (reason: they might be final). * todo: check whether this is still necessary. * (2) Admit the case where an interface proxy throws fewer exceptions * than the method it implements. Augment the proxy methods with the * undeclared exceptions in this case. * (3) In GJ, admit the case where an interface proxy has a result type * extended by the result type of the method it implements. * Change the proxies result type to the smaller type in this case. * * @param tree The tree from which positions * are extracted for errors. * @param m The overriding method. * @param other The overridden method. * @param origin The class of which the overriding method * is a member. */ void checkOverride(Tree tree, MethodSymbol m, MethodSymbol other, ClassSymbol origin) { if ((other.flags() & SYNTHETIC) != 0) { } else if ((m.flags() & STATIC) != 0 && (other.flags() & STATIC) == 0) { log.error(TreeInfo.positionFor(m, tree), "override.static", cannotOverride(m, other)); } else if ((other.flags() & FINAL) != 0 || (m.flags() & STATIC) == 0 && (other.flags() & STATIC) != 0) { log.error(TreeInfo.positionFor(m, tree), "override.meth", cannotOverride(m, other), TreeInfo.flagNames(other.flags() & (FINAL | STATIC))); } else if ((origin.flags() & INTERFACE) == 0 && protection(m.flags()) > protection(other.flags())) { log.error(TreeInfo.positionFor(m, tree), "override.weaker.access", cannotOverride(m, other), protectionString(other.flags())); } else { Type mt = origin.type.memberType(m); Type ot = origin.type.memberType(other); List mtvars = mt.typarams(); List otvars = ot.typarams(); Type otres = ot.restype().subst(otvars, mtvars); boolean resultTypesOK = mt.restype().isSameType(otres); if (!resultTypesOK) { typeError(TreeInfo.positionFor(m, tree), log.getLocalizedString("override.incompatible.ret", cannotOverride(m, other)), mt.restype(), ot.restype().subst(otvars, mtvars)); } else { List otthrown = Type.subst(ot.thrown(), otvars, mtvars); List unhandled = unHandled(mt.thrown(), otthrown); if (unhandled.nonEmpty()) { log.error(TreeInfo.positionFor(m, tree), "override.meth.doesnt.throw", cannotOverride(m, other),
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -