📄 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 + -