📄 check.java
字号:
((Type) unhandled.head).toJava());
}
}
if ((other.flags() & DEPRECATED) != 0 && (m.flags() & DEPRECATED) == 0 &&
m.outermostClass() != other.outermostClass() &&
m.enclClass().type.supertype().tsym == other.enclClass())
warnDeprecated(TreeInfo.positionFor(m, tree), other);
}
}
/**
* Check that a given method conforms with any method it overrides.
* @param tree The tree from which positions are extracted
* for errors.
* @param m The overriding method.
*/
void checkOverride(Tree tree, MethodSymbol m) {
ClassSymbol origin = (ClassSymbol) m.owner;
for (Type t = origin.type.supertype(); t.tag == CLASS; t = t.supertype()) {
TypeSymbol c = t.tsym;
Scope.Entry e = c.members().lookup(m.name);
while (e.scope != null) {
if (m.overrides(e.sym, origin))
checkOverride(tree, m, (MethodSymbol) e.sym, origin);
e = e.next();
}
}
}
/**
* Return the first method which is defined with same args
* but different return types in two given interfaces, or null if none
* exists.
* @param t1 The first interface.
* @param t2 The second interface.
* @param site The most derived type.
*/
public Symbol firstIncompatibility(Type t1, Type t2, Type site) {
return firstIncompatibility(t1, t2, t2, site);
}
/**
* Return the first method which is defined with same args
* but different return types in a type `t1' and a supertype
* `t2super' of a type `t2', or null if none exists.
* @param t1 The first type.
* @param t2 The second type.
* @param t2super The second's supertype.
* @param site The most derived type.
*/
public Symbol firstIncompatibility(Type t1, Type t2, Type t2super, Type site) {
if ((t2super.tsym.flags() & ABSTRACT) == 0)
return null;
for (Scope.Entry e = t2super.tsym.members().elems; e != null; e = e.sibling) {
if (e.sym.kind == MTH && (e.sym.flags() & ABSTRACT) != 0 &&
(site == null || e.sym.isInheritedIn(site.tsym)) &&
!isCompatible(t1, t1, t2, e.sym))
return e.sym;
}
for (List is = t2super.interfaces(); is.nonEmpty(); is = is.tail) {
Symbol sym = firstIncompatibility(t1, t2, (Type) is.head, site);
if (sym != null)
return sym;
}
return (t2super.supertype().tag == CLASS) ?
firstIncompatibility(t1, t2, t2super.supertype(), site) : null;
}
/**
* Check that supertype `t1super' of type `t1' does not define
* an abstract method with with same name and argument types but
* a different return type than its definition in type `t2'.
* @param t1 The first type.
* @param t1super The first type's supertype.
* @param t2 The second type.
* @param sym The method symbol.
*/
private boolean isCompatible(Type t1, Type t1super, Type t2, Symbol sym) {
for (Scope.Entry e = t1super.tsym.members().lookup(sym.name);
e.scope != null; e = e.next()) {
if (e.sym.kind == MTH && (e.sym.flags() & ABSTRACT) != 0) {
Type symt1 = t1.memberType(e.sym);
Type symt2 = t2.memberType(sym);
if (symt1.hasSameArgs(symt2)) {
List tvars1 = symt1.typarams();
List tvars2 = symt2.typarams();
Type rt1 = symt1.restype();
Type rt2 = symt2.restype().subst(tvars2, tvars1);
return rt1.isSameType(rt2);
}
}
}
for (List is = t1super.interfaces(); is.nonEmpty(); is = is.tail) {
if (!isCompatible(t1, (Type) is.head, t2, sym))
return false;
}
return (t1super.supertype().tag == CLASS &&
(t1super.supertype().tsym.flags() & ABSTRACT) != 0) ?
isCompatible(t1, t1super.supertype(), t2, sym) : true;
}
/**
* Check that (arrays of) interfaces do not each define a method
* with same name and arguments but different return types.
* If either argument type is not an (array of) interface type, do
* nothing.
* @param pos Position to be used for error reporting.
* @param t1 The first argument type.
* @param t2 The second argument type.
*/
public boolean checkCompatible(int pos, Type t1, Type t2) {
if (t1.tag == ARRAY && t2.tag == ARRAY) {
checkCompatible(pos, t1.elemtype(), t2.elemtype());
} else if (t1.tag == CLASS && (t1.tsym.flags() & INTERFACE) != 0 &&
t2.tag == CLASS && (t2.tsym.flags() & INTERFACE) != 0) {
return checkCompatibleAbstracts(pos, t1, t2, null);
}
return true;
}
/**
* Check that classes (or interfaces) do not each define an abstract
* method with same name and arguments but different return types.
* @param pos Position to be used for error reporting.
* @param t1 The first argument type.
* @param t2 The second argument type.
*/
public boolean checkCompatibleAbstracts(int pos, Type t1, Type t2, Type site) {
Symbol sym = firstIncompatibility(t1, t2, site);
if (sym != null) {
log.error(pos, "types.incompatible.diff.ret", t1.toJava(), t2.toJava(),
sym.name + "(" + t2.memberType(sym).argtypes() + ")");
return false;
}
return true;
}
/**
* Check that all abstract members of given class have definitions.
* @param pos Position to be used for error reporting.
* @param c The class.
*/
void checkAllDefined(int pos, ClassSymbol c) {
try {
MethodSymbol undef = firstUndef(c, c);
if (undef != null) {
MethodSymbol undef1 = new MethodSymbol(undef.flags(), undef.name,
c.type.memberType(undef), undef.owner);
log.error(pos, "does.not.override.abstract", c.toJava(),
undef1.toJava(), undef1.javaLocation());
}
} catch (CompletionFailure ex) {
completionError(pos, ex);
}
}
/**
* Return first abstract member of class `c' that is not defined
* in `impl', null if there is none.
*/
private MethodSymbol firstUndef(ClassSymbol impl, ClassSymbol c) {
MethodSymbol undef = null;
if (c == impl || (c.flags() & (ABSTRACT | INTERFACE)) != 0) {
Scope s = c.members();
for (Scope.Entry e = s.elems; undef == null && e != null; e = e.sibling) {
if (e.sym.kind == MTH &&
(e.sym.flags() & (ABSTRACT | IPROXY)) == ABSTRACT) {
MethodSymbol absmeth = (MethodSymbol) e.sym;
MethodSymbol implmeth = absmeth.implementation(impl);
if (implmeth == null || implmeth == absmeth)
undef = absmeth;
}
}
if (undef == null) {
Type st = c.type.supertype();
if (st.tag == CLASS)
undef = firstUndef(impl, (ClassSymbol) st.tsym);
}
for (List l = c.type.interfaces(); undef == null && l.nonEmpty();
l = l.tail) {
undef = firstUndef(impl, (ClassSymbol)((Type) l.head).tsym);
}
}
return undef;
}
/**
* 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.
*/
Type checkNonCyclic(int pos, Type t) {
Symbol c = t.tsym;
if ((c.flags_field & LOCKED) != 0) {
log.error(pos, "cyclic.inheritance", c.toJava());
t = new ErrorType((ClassSymbol) c);
} else if ((c.flags_field & ACYCLIC) != 0) {
return t;
} else if (!c.type.isErroneous()) {
try {
c.flags_field |= LOCKED;
for (List l = c.type.interfaces(); l.nonEmpty(); l = l.tail)
l.head = checkNonCyclic(pos, (Type) l.head);
Type st = c.type.supertype();
if (st != null && st.tag == CLASS)
((ClassType) c.type).supertype_field = checkNonCyclic(pos, st);
}
finally { c.flags_field &= ~LOCKED;
} }
c.flags_field |= ACYCLIC;
return t;
}
/**
* 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(ClassDef tree) {
checkImplementations(tree, tree.sym);
}
/**
* Check that all methods which implement some
* method in `ic' conform to the method they implement.
*/
void checkImplementations(ClassDef tree, ClassSymbol ic) {
ClassSymbol origin = tree.sym;
if ((origin != ic) && (ic.flags() & ABSTRACT) != 0) {
for (Scope.Entry e = ic.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);
if (implmeth != null && implmeth != absmeth &&
(implmeth.owner.flags() & INTERFACE) ==
(origin.flags() & INTERFACE)) {
checkOverride(tree, implmeth, absmeth, origin);
}
}
}
}
Type st = ic.type.supertype();
if (st.tag == CLASS)
checkImplementations(tree, (ClassSymbol) st.tsym);
for (List l = ic.type.interfaces(); l.nonEmpty(); l = l.tail)
checkImplementations(tree, (ClassSymbol)((Type) l.head).tsym);
}
/**
* 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(int pos, Type c) {
List supertypes = c.interfaces();
Type supertype = c.supertype();
if (supertype.tag == CLASS && (supertype.tsym.flags() & ABSTRACT) != 0)
supertypes = supertypes.prepend(supertype);
for (List l = supertypes; l.nonEmpty(); l = l.tail) {
for (List m = supertypes; m != l; m = m.tail)
if (!checkCompatibleAbstracts(pos, (Type) l.head, (Type) m.head, c))
return;
}
}
/**
* Enter interface into into set.
* If it existed already, issue a "repeated interface" error.
*/
void checkNotRepeated(int pos, Type it, Set its) {
if (its.contains(it))
log.error(pos, "repeated.interface");
else {
its.put(it);
}
}
/**
* Check for cycles in the graph of constructors calling other
* constructors.
*/
void checkCyclicConstructors(ClassDef tree) {
Hashtable callMap = new Hashtable();
for (List l = tree.defs; l.nonEmpty(); l = l.tail) {
Apply app = TreeInfo.firstConstructorCall((Tree) l.head);
if (app == null)
continue;
MethodDef meth = (MethodDef) l.head;
if (TreeInfo.name(app.meth) == names._this) {
callMap.put(meth.sym, TreeInfo.symbol(app.meth));
} else {
meth.sym.flags_field |= ACYCLIC;
}
}
for (List callers = callMap.keys(); callers.nonEmpty();
callers = callers.tail) {
checkCyclicConstructor(tree, (Symbol) callers.head, callMap);
}
}
/**
* Look in the map to see if the given constructor is part of a
* call cycle.
*/
private void checkCyclicConstructor(ClassDef tree, Symbol ctor,
Hashtable callMap) {
if (ctor != null && (ctor.flags_field & ACYCLIC) == 0) {
if ((ctor.flags_field & LOCKED) != 0) {
log.error(TreeInfo.positionFor(ctor, tree), "recursive.ctor.invocation");
} else {
ctor.flags_field |= LOCKED;
checkCyclicConstructor(tree, (Symbol) callMap.remove(ctor), callMap);
ctor.flags_field &= ~LOCKED;
}
ctor.flags_field |= ACYCLIC;
}
}
/**
* Check that a qualified name is in canonical form (for import decls).
*/
public void checkCanonical(Tree tree) {
if (!isCanonical(tree))
log.error(tree.pos, "import.requires.canonical",
TreeInfo.symbol(tree).toJava());
}
private boolean isCanonical(Tree tree) {
while (tree.tag == Tree.SELECT) {
Select s = (Select) tree;
if (s.sym.owner != TreeInfo.symbol(s.selected))
return false;
tree = s.selected;
}
return true;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -