aboutsummaryrefslogtreecommitdiff
path: root/src/core/lombok/javac
diff options
context:
space:
mode:
authorReinier Zwitserloot <r.zwitserloot@projectlombok.org>2020-07-23 23:33:27 +0200
committerReinier Zwitserloot <r.zwitserloot@projectlombok.org>2020-07-23 23:33:41 +0200
commitc00317220523c42ae0cc459fa3526c641e37f2af (patch)
tree6999e62b344b576fdc35445406402745967a473f /src/core/lombok/javac
parent5175725eee22c842e3e41d2529be46f5621d047a (diff)
downloadlombok-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.
Diffstat (limited to 'src/core/lombok/javac')
-rw-r--r--src/core/lombok/javac/JavacResolution.java62
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");
}