diff options
Diffstat (limited to 'src/core/lombok/javac/JavacResolution.java')
-rw-r--r-- | src/core/lombok/javac/JavacResolution.java | 66 |
1 files changed, 62 insertions, 4 deletions
diff --git a/src/core/lombok/javac/JavacResolution.java b/src/core/lombok/javac/JavacResolution.java index 9a0077a7..6b2f4637 100644 --- a/src/core/lombok/javac/JavacResolution.java +++ b/src/core/lombok/javac/JavacResolution.java @@ -28,7 +28,10 @@ import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.ArrayDeque; +import java.util.Collection; +import java.util.Iterator; import java.util.Map; +import java.util.NoSuchElementException; import javax.lang.model.type.TypeKind; import javax.tools.JavaFileObject; @@ -40,6 +43,7 @@ import com.sun.tools.javac.code.Type; import com.sun.tools.javac.code.Type.ArrayType; import com.sun.tools.javac.code.Type.CapturedType; import com.sun.tools.javac.code.Type.ClassType; +import com.sun.tools.javac.code.Type.TypeVar; import com.sun.tools.javac.code.Type.WildcardType; import com.sun.tools.javac.code.Types; import com.sun.tools.javac.comp.Attr; @@ -59,6 +63,7 @@ import com.sun.tools.javac.util.Context; import com.sun.tools.javac.util.List; import com.sun.tools.javac.util.ListBuffer; import com.sun.tools.javac.util.Log; +import com.sun.tools.javac.util.Name; import lombok.Lombok; import lombok.core.debug.AssertionLogger; @@ -314,6 +319,41 @@ public class JavacResolution { return result; } + private static Iterable<? extends Type> concat(final Type t, final Collection<? extends Type> ts) { + if (t == null) return ts; + + return new Iterable<Type>() { + @Override public Iterator<Type> iterator() { + return new Iterator<Type>() { + private boolean first = true; + private Iterator<? extends Type> wrap = ts == null ? null : ts.iterator(); + @Override public boolean hasNext() { + if (first) return true; + if (wrap == null) return false; + return wrap.hasNext(); + } + + @Override public Type next() { + if (first) { + first = false; + return t; + } + if (wrap == null) throw new NoSuchElementException(); + return wrap.next(); + } + + @Override public void remove() { + throw new UnsupportedOperationException(); + } + }; + } + }; + } + + private static int compare(Name a, Name b) { + return a.compareTo(b); + } + private static JCExpression typeToJCTree0(Type type, JavacAST ast, boolean allowCompound, boolean allowVoid, boolean allowCapture) throws TypeNotConvertibleException { // NB: There's such a thing as maker.Type(type), but this doesn't work very well; it screws up anonymous classes, captures, and adds an extra prefix dot for some reason too. // -- so we write our own take on that here. @@ -335,12 +375,30 @@ public class JavacResolution { if (symbol.name.length() == 0) { // Anonymous inner class if (type instanceof ClassType) { - List<Type> ifaces = ((ClassType) type).interfaces_field; + Type winner = null; + int winLevel = 0; // 100 = array, 50 = class, 20 = typevar, 15 = wildcard, 10 = interface, 1 = Object. Type supertype = ((ClassType) type).supertype_field; - if (isObject(supertype) && ifaces != null && ifaces.length() > 0) { - return typeToJCTree(ifaces.get(0), ast, allowCompound, allowVoid, allowCapture); + List<Type> ifaces = ((ClassType) type).interfaces_field; + for (Type t : concat(supertype, ifaces)) { + int level = 0; + if (t instanceof ArrayType) level = 100; + else if (t instanceof TypeVar) level = 20; + else if (t instanceof WildcardType) level = 15; + else if (t.isInterface()) level = 10; + else if (isObject(t)) level = 1; + else if (t instanceof ClassType) level = 50; + else level = 5; + + if (winLevel > level) continue; + if (winLevel < level) { + winner = t; + winLevel = level; + continue; + } + if (compare(winner.tsym.getQualifiedName(), t.tsym.getQualifiedName()) < 0) winner = t; } - if (supertype != null) return typeToJCTree(supertype, ast, allowCompound, allowVoid, allowCapture); + if (winner == null) return createJavaLangObject(ast); + return typeToJCTree(winner, ast, allowCompound, allowVoid, allowCapture); } throw new TypeNotConvertibleException("Anonymous inner class"); } |