--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java Fri Jan 16 12:02:41 2015 +0000
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java Fri Jan 16 14:47:25 2015 +0100
@@ -48,6 +48,7 @@
import static com.sun.tools.javac.code.Flags.*;
import static com.sun.tools.javac.code.Kinds.Kind.*;
import static com.sun.tools.javac.code.Scope.*;
+import static com.sun.tools.javac.code.Scope.LookupKind.NON_RECURSIVE;
import static com.sun.tools.javac.code.Symbol.*;
import static com.sun.tools.javac.code.Type.*;
import static com.sun.tools.javac.code.TypeTag.*;
@@ -82,6 +83,7 @@
final JavacMessages messages;
final Names names;
final boolean allowObjectToPrimitiveCast;
+ final boolean allowDefaultMethods;
final Check chk;
final Enter enter;
JCDiagnostic.Factory diags;
@@ -105,6 +107,7 @@
names = Names.instance(context);
Source source = Source.instance(context);
allowObjectToPrimitiveCast = source.allowObjectToPrimitiveCast();
+ allowDefaultMethods = source.allowDefaultMethods();
chk = Check.instance(context);
enter = Enter.instance(context);
capturedName = names.fromString("<captured wildcard>");
@@ -2775,6 +2778,58 @@
// </editor-fold>
+ /** Return first abstract member of class `sym'.
+ */
+ public MethodSymbol firstUnimplementedAbstract(ClassSymbol sym) {
+ try {
+ return firstUnimplementedAbstractImpl(sym, sym);
+ } catch (CompletionFailure ex) {
+ chk.completionError(enter.getEnv(sym).tree.pos(), ex);
+ return null;
+ }
+ }
+ //where:
+ private MethodSymbol firstUnimplementedAbstractImpl(ClassSymbol impl, ClassSymbol c) {
+ MethodSymbol undef = null;
+ // Do not bother to search in classes that are not abstract,
+ // since they cannot have abstract members.
+ if (c == impl || (c.flags() & (ABSTRACT | INTERFACE)) != 0) {
+ Scope s = c.members();
+ for (Symbol sym : s.getSymbols(NON_RECURSIVE)) {
+ if (sym.kind == MTH &&
+ (sym.flags() & (ABSTRACT|IPROXY|DEFAULT)) == ABSTRACT) {
+ MethodSymbol absmeth = (MethodSymbol)sym;
+ MethodSymbol implmeth = absmeth.implementation(impl, this, true);
+ if (implmeth == null || implmeth == absmeth) {
+ //look for default implementations
+ if (allowDefaultMethods) {
+ MethodSymbol prov = interfaceCandidates(impl.type, absmeth).head;
+ if (prov != null && prov.overrides(absmeth, impl, this, true)) {
+ implmeth = prov;
+ }
+ }
+ }
+ if (implmeth == null || implmeth == absmeth) {
+ undef = absmeth;
+ break;
+ }
+ }
+ }
+ if (undef == null) {
+ Type st = supertype(c.type);
+ if (st.hasTag(CLASS))
+ undef = firstUnimplementedAbstractImpl(impl, (ClassSymbol)st.tsym);
+ }
+ for (List<Type> l = interfaces(c.type);
+ undef == null && l.nonEmpty();
+ l = l.tail) {
+ undef = firstUnimplementedAbstractImpl(impl, (ClassSymbol)l.head.tsym);
+ }
+ }
+ return undef;
+ }
+
+
//where
public List<MethodSymbol> interfaceCandidates(Type site, MethodSymbol ms) {
Filter<Symbol> filter = new MethodFilter(ms, site);