📄 check.java
字号:
if (tree != null) tree.accept(validator); } catch (CompletionFailure ex) { completionError(tree.pos(), ex); } } /** Visitor method: Validate a list of type expressions. */ void validate(List<? extends JCTree> trees) { for (List<? extends JCTree> l = trees; l.nonEmpty(); l = l.tail) validate(l.head); } /** Visitor method: Validate a list of type parameters. */ void validateTypeParams(List<JCTypeParameter> trees) { for (List<JCTypeParameter> l = trees; l.nonEmpty(); l = l.tail) validate(l.head); } /** A visitor class for type validation. */ class Validator extends JCTree.Visitor { public void visitTypeArray(JCArrayTypeTree tree) { validate(tree.elemtype); } public void visitTypeApply(JCTypeApply tree) { if (tree.type.tag == CLASS) { List<Type> formals = tree.type.tsym.type.getTypeArguments(); List<Type> actuals = tree.type.getTypeArguments(); List<JCExpression> args = tree.arguments; List<Type> forms = formals; ListBuffer<TypeVar> tvars_buf = new ListBuffer<TypeVar>(); // For matching pairs of actual argument types `a' and // formal type parameters with declared bound `b' ... while (args.nonEmpty() && forms.nonEmpty()) { validate(args.head); // exact type arguments needs to know their // bounds (for upper and lower bound // calculations). So we create new TypeVars with // bounds substed with actuals. tvars_buf.append(types.substBound(((TypeVar)forms.head), formals, Type.removeBounds(actuals))); args = args.tail; forms = forms.tail; } args = tree.arguments; List<TypeVar> tvars = tvars_buf.toList(); while (args.nonEmpty() && tvars.nonEmpty()) { // Let the actual arguments know their bound args.head.type.withTypeVar(tvars.head); args = args.tail; tvars = tvars.tail; } args = tree.arguments; tvars = tvars_buf.toList(); while (args.nonEmpty() && tvars.nonEmpty()) { checkExtends(args.head.pos(), args.head.type, tvars.head); args = args.tail; tvars = tvars.tail; } // Check that this type is either fully parameterized, or // not parameterized at all. if (tree.type.getEnclosingType().isRaw()) log.error(tree.pos(), "improperly.formed.type.inner.raw.param"); if (tree.clazz.getTag() == JCTree.SELECT) visitSelectInternal((JCFieldAccess)tree.clazz); } } public void visitTypeParameter(JCTypeParameter tree) { validate(tree.bounds); checkClassBounds(tree.pos(), tree.type); } @Override public void visitWildcard(JCWildcard tree) { if (tree.inner != null) validate(tree.inner); } public void visitSelect(JCFieldAccess tree) { if (tree.type.tag == CLASS) { visitSelectInternal(tree); // Check that this type is either fully parameterized, or // not parameterized at all. if (tree.selected.type.isParameterized() && tree.type.tsym.type.getTypeArguments().nonEmpty()) log.error(tree.pos(), "improperly.formed.type.param.missing"); } } public void visitSelectInternal(JCFieldAccess tree) { if (tree.type.getEnclosingType().tag != CLASS && tree.selected.type.isParameterized()) { // The enclosing type is not a class, so we are // looking at a static member type. However, the // qualifying expression is parameterized. log.error(tree.pos(), "cant.select.static.class.from.param.type"); } else { // otherwise validate the rest of the expression validate(tree.selected); } } /** Default visitor method: do nothing. */ public void visitTree(JCTree tree) { } }/* ************************************************************************* * Exception checking **************************************************************************/ /* The following methods treat classes as sets that contain * the class itself and all their subclasses */ /** Is given type a subtype of some of the types in given list? */ boolean subset(Type t, List<Type> ts) { for (List<Type> l = ts; l.nonEmpty(); l = l.tail) if (types.isSubtype(t, l.head)) return true; return false; } /** Is given type a subtype or supertype of * some of the types in given list? */ boolean intersects(Type t, List<Type> ts) { for (List<Type> l = ts; l.nonEmpty(); l = l.tail) if (types.isSubtype(t, l.head) || types.isSubtype(l.head, t)) return true; return false; } /** Add type set to given type list, unless it is a subclass of some class * in the list. */ List<Type> incl(Type t, List<Type> ts) { return subset(t, ts) ? ts : excl(t, ts).prepend(t); } /** Remove type set from type set list. */ List<Type> excl(Type t, List<Type> ts) { if (ts.isEmpty()) { return ts; } else { List<Type> ts1 = excl(t, ts.tail); if (types.isSubtype(ts.head, t)) return ts1; else if (ts1 == ts.tail) return ts; else return ts1.prepend(ts.head); } } /** Form the union of two type set lists. */ List<Type> union(List<Type> ts1, List<Type> ts2) { List<Type> ts = ts1; for (List<Type> l = ts2; l.nonEmpty(); l = l.tail) ts = incl(l.head, ts); return ts; } /** Form the difference of two type lists. */ List<Type> diff(List<Type> ts1, List<Type> ts2) { List<Type> ts = ts1; for (List<Type> l = ts2; l.nonEmpty(); l = l.tail) ts = excl(l.head, ts); return ts; } /** Form the intersection of two type lists. */ public List<Type> intersect(List<Type> ts1, List<Type> ts2) { List<Type> ts = List.nil(); for (List<Type> l = ts1; l.nonEmpty(); l = l.tail) if (subset(l.head, ts2)) ts = incl(l.head, ts); for (List<Type> l = ts2; l.nonEmpty(); l = l.tail) if (subset(l.head, ts1)) ts = incl(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, types) || exc.isSubClass(syms.runtimeExceptionType.tsym, types); } /** Is exc an exception type that need not be declared? */ boolean isUnchecked(Type exc) { return (exc.tag == TYPEVAR) ? isUnchecked(types.supertype(exc)) : (exc.tag == CLASS) ? isUnchecked((ClassSymbol)exc.tsym) : exc.tag == BOT; } /** Same, but handling completion failures. */ boolean isUnchecked(DiagnosticPosition 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<Type> 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<Type> unHandled(List<Type> thrown, List<Type> handled) { List<Type> unhandled = List.nil(); for (List<Type> l = thrown; l.nonEmpty(); l = l.tail) if (!isHandled(l.head, handled)) unhandled = unhandled.prepend(l.head); return unhandled; }/* ************************************************************************* * Overriding/Implementation checking **************************************************************************/ /** 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; default: case PUBLIC: return 0; case 0: 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 Object cannotOverride(MethodSymbol m, MethodSymbol other) { String key; if ((other.owner.flags() & INTERFACE) == 0) key = "cant.override"; else if ((m.owner.flags() & INTERFACE) == 0) key = "cant.implement"; else key = "clashes.with"; return JCDiagnostic.fragment(key, m, m.location(), other, other.location()); } /** A customized "override" warning message. * @param m The overriding method. * @param other The overridden method. * @return An internationalized string. */ static Object uncheckedOverrides(MethodSymbol m, MethodSymbol other) { String key; if ((other.owner.flags() & INTERFACE) == 0) key = "unchecked.override"; else if ((m.owner.flags() & INTERFACE) == 0) key = "unchecked.implement"; else key = "unchecked.clash.with"; return JCDiagnostic.fragment(key, m, m.location(), other, other.location()); } /** A customized "override" warning message. * @param m The overriding method. * @param other The overridden method. * @return An internationalized string. */ static Object varargsOverrides(MethodSymbol m, MethodSymbol other) { String key; if ((other.owner.flags() & INTERFACE) == 0) key = "varargs.override"; else if ((m.owner.flags() & INTERFACE) == 0) key = "varargs.implement"; else key = "varargs.clash.with"; return JCDiagnostic.fragment(key, m, m.location(), other, other.location()); } /** 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) When generics are enabled, 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(JCTree tree, MethodSymbol m, MethodSymbol other, ClassSymbol origin) { // Don't check overriding of synthetic methods or by bridge methods. if ((m.flags() & (SYNTHETIC|BRIDGE)) != 0 || (other.flags() & SYNTHETIC) != 0) { return; } // Error if static method overrides instance method (JLS 8.4.6.2). if ((m.flags() & STATIC) != 0 && (other.flags() & STATIC) == 0) { log.error(TreeInfo.diagnosticPositionFor(m, tree), "override.static", cannotOverride(m, other)); return; } // Error if instance method overrides static or final // method (JLS 8.4.6.1). if ((other.flags() & FINAL) != 0 || (m.flags() & STATIC) == 0 && (other.flags() & STATIC) != 0) { log.error(TreeInfo.diagnosticPositionFor(m, tree), "override.meth", cannotOverride(m, other), TreeInfo.flagNames(other.flags() & (FINAL | STATIC))); return; } if ((m.owner.flags() & ANNOTATION) != 0) { // handled in validateAnnotationMethod return; } // Error if overriding method has weaker access (JLS 8.4.6.3). if ((origin.flags() & INTERFACE) == 0 && protection(m.flags()) > protection(other.flags())) { log.error(TreeInfo.diagnosticPositionFor(m, tree), "override.weaker.access",
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -