diff options
author | Reinier Zwitserloot <r.zwitserloot@projectlombok.org> | 2020-07-23 23:33:27 +0200 |
---|---|---|
committer | Reinier Zwitserloot <r.zwitserloot@projectlombok.org> | 2020-07-23 23:33:41 +0200 |
commit | c00317220523c42ae0cc459fa3526c641e37f2af (patch) | |
tree | 6999e62b344b576fdc35445406402745967a473f | |
parent | 5175725eee22c842e3e41d2529be46f5621d047a (diff) | |
download | lombok-c00317220523c42ae0cc459fa3526c641e37f2af.tar.gz lombok-c00317220523c42ae0cc459fa3526c641e37f2af.tar.bz2 lombok-c00317220523c42ae0cc459fa3526c641e37f2af.zip |
[bugfix] [javac] LUB types + val
Until recently, we'd 'resolve' LUB (compound) types in val constructs by just taking the first one in the line of interfaces. The problem is, different versions of different compilers use different orderings. In an earlier commit, the eclipse impl gained a new algorithm that is more stable, e.g. by sorting on alphabet. now the javac side has the same algorithm.
-rw-r--r-- | src/core/lombok/javac/JavacResolution.java | 62 |
1 files changed, 58 insertions, 4 deletions
diff --git a/src/core/lombok/javac/JavacResolution.java b/src/core/lombok/javac/JavacResolution.java index 9a0077a7..98bf3c4b 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,37 @@ 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(); + } + }; + } + }; + } + + 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 +371,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"); } |