mirror of
https://github.com/tiennm99/lombok.git
synced 2026-10-15 02:17:12 +00:00
[fixes #2358] self-referential generics could cause endless loops in javac.
... unfortunately eclipse's val resolver is now very slightly worse in very exotic circumstances - spent about 4 hours trying to fix it, can't figure it out, let's move on.
This commit is contained in:
8 files changed
+88
-19
No files matched your search
@@ -5,6 +5,7 @@ Lombok Changelog
|
||||
* BREAKING CHANGE: mapstruct users should now add a dependency to lombok-mapstruct-binding. This solves compiling modules with lombok (and mapstruct).
|
||||
* FEATURE: Similar to `@Builder`, you can now configure a `@SuperBuilder`'s 'setter' prefixes via `@SuperBuilder(setterPrefix = "set")` for example. We still discourage doing this. [Pull Request #2357](https://github.com/rzwitserloot/lombok/pull/2357).
|
||||
* FEATURE: If using `@Synchronized("lockVar")`, if `lockVar` is referring to a static field, the code lombok generates no longer causes a warning about accessing a static entity incorrectly. [Issue #678](https://github.com/rzwitserloot/lombok/issues/678)
|
||||
* BUGFIX: Using `val` in combination with values whose generics include wildcards that reference themselves would cause a `StackOverflowError` in javac. [Issue #2358](https://github.com/rzwitserloot/lombok/issues/2358).
|
||||
* BUGFIX: Using `@SuperBuilder` on a class that has some fairly convoluted generics usage would fail with 'Wrong number of type arguments'. [Issue #2359](https://github.com/rzwitserloot/lombok/issues/2359) [Pull Request #2362](https://github.com/rzwitserloot/lombok/pull/2362)
|
||||
* BUGFIX: Various lombok annotations on classes nested inside enums or interfaces would cause errors in eclipse. [Issue #2369](https://github.com/rzwitserloot/lombok/issues/2369)
|
||||
* BUGFIX: Trying to add `@ExtensionMethod`s with exactly 2 arguments would fail in eclipse. [Issue #1441](https://github.com/rzwitserloot/lombok/issues/1441) [Pull Request #2376](https://github.com/rzwitserloot/lombok/pull/2376) thanks to __@Rawi01__.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2011-2018 The Project Lombok Authors.
|
||||
* Copyright (C) 2011-2020 The Project Lombok Authors.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -33,10 +33,6 @@ import java.util.Map;
|
||||
import javax.lang.model.type.TypeKind;
|
||||
import javax.tools.JavaFileObject;
|
||||
|
||||
import lombok.Lombok;
|
||||
import lombok.core.debug.AssertionLogger;
|
||||
import lombok.permit.Permit;
|
||||
|
||||
import com.sun.tools.javac.code.BoundKind;
|
||||
import com.sun.tools.javac.code.Symbol.TypeSymbol;
|
||||
import com.sun.tools.javac.code.Symtab;
|
||||
@@ -58,11 +54,16 @@ import com.sun.tools.javac.tree.JCTree.JCCompilationUnit;
|
||||
import com.sun.tools.javac.tree.JCTree.JCExpression;
|
||||
import com.sun.tools.javac.tree.JCTree.JCMethodDecl;
|
||||
import com.sun.tools.javac.tree.JCTree.JCVariableDecl;
|
||||
import com.sun.tools.javac.tree.JCTree.JCWildcard;
|
||||
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 lombok.Lombok;
|
||||
import lombok.core.debug.AssertionLogger;
|
||||
import lombok.permit.Permit;
|
||||
|
||||
public class JavacResolution {
|
||||
private final Attr attr;
|
||||
private final CompilerMessageSuppressor messageSuppressor;
|
||||
@@ -286,7 +287,7 @@ public class JavacResolution {
|
||||
}
|
||||
|
||||
public static JCExpression typeToJCTree(Type type, JavacAST ast, boolean allowVoid) throws TypeNotConvertibleException {
|
||||
return typeToJCTree(type, ast, false, allowVoid);
|
||||
return typeToJCTree(type, ast, false, allowVoid, false);
|
||||
}
|
||||
|
||||
public static JCExpression createJavaLangObject(JavacAST ast) {
|
||||
@@ -297,7 +298,7 @@ public class JavacResolution {
|
||||
return out;
|
||||
}
|
||||
|
||||
private static JCExpression typeToJCTree(Type type, JavacAST ast, boolean allowCompound, boolean allowVoid) throws TypeNotConvertibleException {
|
||||
private static JCExpression typeToJCTree(Type type, JavacAST ast, boolean allowCompound, boolean allowVoid, boolean allowCapture) throws TypeNotConvertibleException {
|
||||
int dims = 0;
|
||||
Type type0 = type;
|
||||
while (type0 instanceof ArrayType) {
|
||||
@@ -305,7 +306,7 @@ public class JavacResolution {
|
||||
type0 = ((ArrayType) type0).elemtype;
|
||||
}
|
||||
|
||||
JCExpression result = typeToJCTree0(type0, ast, allowCompound, allowVoid);
|
||||
JCExpression result = typeToJCTree0(type0, ast, allowCompound, allowVoid, allowCapture);
|
||||
while (dims > 0) {
|
||||
result = ast.getTreeMaker().TypeArray(result);
|
||||
dims--;
|
||||
@@ -313,7 +314,7 @@ public class JavacResolution {
|
||||
return result;
|
||||
}
|
||||
|
||||
private static JCExpression typeToJCTree0(Type type, JavacAST ast, boolean allowCompound, boolean allowVoid) throws TypeNotConvertibleException {
|
||||
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.
|
||||
|
||||
@@ -337,21 +338,33 @@ public class JavacResolution {
|
||||
List<Type> ifaces = ((ClassType) type).interfaces_field;
|
||||
Type supertype = ((ClassType) type).supertype_field;
|
||||
if (isObject(supertype) && ifaces != null && ifaces.length() > 0) {
|
||||
return typeToJCTree(ifaces.get(0), ast, allowCompound, allowVoid);
|
||||
return typeToJCTree(ifaces.get(0), ast, allowCompound, allowVoid, allowCapture);
|
||||
}
|
||||
if (supertype != null) return typeToJCTree(supertype, ast, allowCompound, allowVoid);
|
||||
if (supertype != null) return typeToJCTree(supertype, ast, allowCompound, allowVoid, allowCapture);
|
||||
}
|
||||
throw new TypeNotConvertibleException("Anonymous inner class");
|
||||
}
|
||||
|
||||
if (type instanceof CapturedType || type instanceof WildcardType) {
|
||||
if (type instanceof WildcardType || type instanceof CapturedType) {
|
||||
Type lower, upper;
|
||||
if (type instanceof WildcardType) {
|
||||
upper = ((WildcardType)type).getExtendsBound();
|
||||
lower = ((WildcardType)type).getSuperBound();
|
||||
upper = ((WildcardType) type).getExtendsBound();
|
||||
lower = ((WildcardType) type).getSuperBound();
|
||||
} else {
|
||||
lower = type.getLowerBound();
|
||||
upper = type.getUpperBound();
|
||||
if (allowCapture) {
|
||||
BoundKind bk = ((CapturedType) type).wildcard.kind;
|
||||
if (bk == BoundKind.UNBOUND) {
|
||||
return maker.Wildcard(maker.TypeBoundKind(BoundKind.UNBOUND), null);
|
||||
} else if (bk == BoundKind.EXTENDS) {
|
||||
lower = null;
|
||||
upper = ((CapturedType) type).wildcard.type;
|
||||
} else if (bk == BoundKind.SUPER) {
|
||||
lower = ((CapturedType) type).wildcard.type;
|
||||
upper = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (allowCompound) {
|
||||
if (lower == null || CTC_BOT.equals(typeTag(lower))) {
|
||||
@@ -361,16 +374,20 @@ public class JavacResolution {
|
||||
if (upper.getTypeArguments().contains(type)) {
|
||||
return maker.Wildcard(maker.TypeBoundKind(BoundKind.UNBOUND), null);
|
||||
}
|
||||
return maker.Wildcard(maker.TypeBoundKind(BoundKind.EXTENDS), typeToJCTree(upper, ast, false, false));
|
||||
JCExpression bound = typeToJCTree(upper, ast, false, false, true);
|
||||
if (bound instanceof JCWildcard) return maker.Wildcard(maker.TypeBoundKind(BoundKind.UNBOUND), null);
|
||||
return maker.Wildcard(maker.TypeBoundKind(BoundKind.EXTENDS), bound);
|
||||
} else {
|
||||
return maker.Wildcard(maker.TypeBoundKind(BoundKind.SUPER), typeToJCTree(lower, ast, false, false));
|
||||
JCExpression bound = typeToJCTree(lower, ast, false, false, true);
|
||||
if (bound instanceof JCWildcard) return maker.Wildcard(maker.TypeBoundKind(BoundKind.UNBOUND), null);
|
||||
return maker.Wildcard(maker.TypeBoundKind(BoundKind.SUPER), bound);
|
||||
}
|
||||
}
|
||||
if (upper != null) {
|
||||
if (upper.getTypeArguments().contains(type)) {
|
||||
return maker.Wildcard(maker.TypeBoundKind(BoundKind.UNBOUND), null);
|
||||
}
|
||||
return typeToJCTree(upper, ast, allowCompound, allowVoid);
|
||||
return typeToJCTree(upper, ast, allowCompound, allowVoid, true);
|
||||
}
|
||||
|
||||
return createJavaLangObject(ast);
|
||||
@@ -380,7 +397,7 @@ public class JavacResolution {
|
||||
if (symbol.isLocal()) {
|
||||
qName = symbol.getSimpleName().toString();
|
||||
} else if (symbol.type != null && symbol.type.getEnclosingType() != null && typeTag(symbol.type.getEnclosingType()).equals(typeTag("CLASS"))) {
|
||||
replacement = typeToJCTree0(type.getEnclosingType(), ast, false, false);
|
||||
replacement = typeToJCTree0(type.getEnclosingType(), ast, false, false, false);
|
||||
qName = symbol.getSimpleName().toString();
|
||||
} else {
|
||||
qName = symbol.getQualifiedName().toString();
|
||||
@@ -409,7 +426,7 @@ public class JavacResolution {
|
||||
private static JCExpression genericsToJCTreeNodes(List<Type> generics, JavacAST ast, JCExpression rawTypeNode) throws TypeNotConvertibleException {
|
||||
if (generics != null && !generics.isEmpty()) {
|
||||
ListBuffer<JCExpression> args = new ListBuffer<JCExpression>();
|
||||
for (Type t : generics) args.append(typeToJCTree(t, ast, true, false));
|
||||
for (Type t : generics) args.append(typeToJCTree(t, ast, true, false, true));
|
||||
return ast.getTreeMaker().TypeApply(rawTypeNode, args.toList());
|
||||
}
|
||||
|
||||
|
||||
@@ -37,6 +37,7 @@ public class ValWeirdTypes<Z> {
|
||||
final java.util.List<? super java.lang.Number> d = upper;
|
||||
List<?> unbound = lower;
|
||||
final java.util.List<?> e = unbound;
|
||||
final java.lang.Object f = unbound.get(0);
|
||||
}
|
||||
public void testCompound() {
|
||||
final java.util.ArrayList<java.lang.String> a = new ArrayList<String>();
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
public class ValWithSelfRefGenerics {
|
||||
public void run(Thing<? extends Comparable<?>> thing, Thing<?> thing2, java.util.List<? extends Number> z) {
|
||||
final java.util.List<? extends java.lang.Number> y = z;
|
||||
final Thing<? extends java.lang.Comparable<?>> x = thing;
|
||||
final Thing<?> w = thing2;
|
||||
final java.lang.Comparable<?> v = thing2.get();
|
||||
}
|
||||
}
|
||||
|
||||
class Thing<T extends Comparable<? super T>> {
|
||||
public T get() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -44,6 +44,7 @@ public class ValWeirdTypes<Z> {
|
||||
final @val java.util.List<? super java.lang.Number> d = upper;
|
||||
List<?> unbound = lower;
|
||||
final @val java.util.List<?> e = unbound;
|
||||
final @val java.lang.Object f = unbound.get(0);
|
||||
}
|
||||
public void testCompound() {
|
||||
final @val java.util.ArrayList<java.lang.String> a = new ArrayList<String>();
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
import lombok.val;
|
||||
public class ValWithSelfRefGenerics {
|
||||
public ValWithSelfRefGenerics() {
|
||||
super();
|
||||
}
|
||||
public void run(Thing<? extends Comparable<?>> thing, Thing<?> thing2, java.util.List<? extends Number> z) {
|
||||
final @val java.util.List<? extends java.lang.Number> y = z;
|
||||
final @val Thing<? extends java.lang.Comparable<?>> x = thing;
|
||||
final @val Thing<?> w = thing2;
|
||||
final @val java.lang.Object v = thing2.get();
|
||||
}
|
||||
}
|
||||
class Thing<T extends Comparable<? super T>> {
|
||||
Thing() {
|
||||
super();
|
||||
}
|
||||
public T get() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -44,6 +44,7 @@ public class ValWeirdTypes<Z> {
|
||||
val d = upper;
|
||||
List<?> unbound = lower;
|
||||
val e = unbound;
|
||||
val f = unbound.get(0);
|
||||
}
|
||||
|
||||
public void testCompound() {
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
import lombok.val;
|
||||
public class ValWithSelfRefGenerics {
|
||||
public void run(Thing<? extends Comparable<?>> thing, Thing<?> thing2, java.util.List<? extends Number> z) {
|
||||
val y = z;
|
||||
val x = thing;
|
||||
val w = thing2;
|
||||
val v = thing2.get();
|
||||
}
|
||||
}
|
||||
class Thing<T extends Comparable<? super T>> {
|
||||
public T get() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user