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