mirror of
https://github.com/tiennm99/lombok.git
synced 2026-09-03 06:19:14 +00:00
Fix for issue 396: Static constructors generated for classes with type parameters did not work in javac.
This commit is contained in:
@@ -43,12 +43,10 @@ import com.sun.tools.javac.tree.JCTree.JCBlock;
|
||||
import com.sun.tools.javac.tree.JCTree.JCClassDecl;
|
||||
import com.sun.tools.javac.tree.JCTree.JCExpression;
|
||||
import com.sun.tools.javac.tree.JCTree.JCFieldAccess;
|
||||
import com.sun.tools.javac.tree.JCTree.JCIdent;
|
||||
import com.sun.tools.javac.tree.JCTree.JCMethodDecl;
|
||||
import com.sun.tools.javac.tree.JCTree.JCModifiers;
|
||||
import com.sun.tools.javac.tree.JCTree.JCReturn;
|
||||
import com.sun.tools.javac.tree.JCTree.JCStatement;
|
||||
import com.sun.tools.javac.tree.JCTree.JCTypeApply;
|
||||
import com.sun.tools.javac.tree.JCTree.JCTypeParameter;
|
||||
import com.sun.tools.javac.tree.JCTree.JCVariableDecl;
|
||||
import com.sun.tools.javac.util.List;
|
||||
@@ -268,16 +266,7 @@ public class HandleConstructor {
|
||||
|
||||
for (JavacNode fieldNode : fields) {
|
||||
JCVariableDecl field = (JCVariableDecl) fieldNode.get();
|
||||
JCExpression pType;
|
||||
if (field.vartype instanceof JCIdent) pType = maker.Ident(((JCIdent)field.vartype).name);
|
||||
else if (field.vartype instanceof JCTypeApply) {
|
||||
JCTypeApply typeApply = (JCTypeApply) field.vartype;
|
||||
ListBuffer<JCExpression> tArgs = ListBuffer.lb();
|
||||
for (JCExpression arg : typeApply.arguments) tArgs.append(arg);
|
||||
pType = maker.TypeApply(typeApply.clazz, tArgs.toList());
|
||||
} else {
|
||||
pType = field.vartype;
|
||||
}
|
||||
JCExpression pType = cloneType(maker, field.vartype, source);
|
||||
List<JCAnnotation> nonNulls = findAnnotations(fieldNode, TransformationsUtil.NON_NULL_PATTERN);
|
||||
List<JCAnnotation> nullables = findAnnotations(fieldNode, TransformationsUtil.NULLABLE_PATTERN);
|
||||
JCVariableDecl param = maker.VarDef(maker.Modifiers(Flags.FINAL, nonNulls.appendList(nullables)), field.name, pType, null);
|
||||
|
||||
@@ -45,14 +45,17 @@ import lombok.experimental.Accessors;
|
||||
import lombok.javac.Javac;
|
||||
import lombok.javac.JavacNode;
|
||||
|
||||
import com.sun.tools.javac.code.BoundKind;
|
||||
import com.sun.tools.javac.code.Flags;
|
||||
import com.sun.tools.javac.code.TypeTags;
|
||||
import com.sun.tools.javac.tree.JCTree;
|
||||
import com.sun.tools.javac.tree.JCTree.JCAnnotation;
|
||||
import com.sun.tools.javac.tree.JCTree.JCArrayTypeTree;
|
||||
import com.sun.tools.javac.tree.JCTree.JCAssign;
|
||||
import com.sun.tools.javac.tree.JCTree.JCClassDecl;
|
||||
import com.sun.tools.javac.tree.JCTree.JCCompilationUnit;
|
||||
import com.sun.tools.javac.tree.JCTree.JCExpression;
|
||||
import com.sun.tools.javac.tree.JCTree.JCFieldAccess;
|
||||
import com.sun.tools.javac.tree.JCTree.JCIdent;
|
||||
import com.sun.tools.javac.tree.JCTree.JCImport;
|
||||
import com.sun.tools.javac.tree.JCTree.JCLiteral;
|
||||
@@ -60,8 +63,12 @@ import com.sun.tools.javac.tree.JCTree.JCMethodDecl;
|
||||
import com.sun.tools.javac.tree.JCTree.JCMethodInvocation;
|
||||
import com.sun.tools.javac.tree.JCTree.JCModifiers;
|
||||
import com.sun.tools.javac.tree.JCTree.JCNewArray;
|
||||
import com.sun.tools.javac.tree.JCTree.JCPrimitiveTypeTree;
|
||||
import com.sun.tools.javac.tree.JCTree.JCStatement;
|
||||
import com.sun.tools.javac.tree.JCTree.JCTypeApply;
|
||||
import com.sun.tools.javac.tree.JCTree.JCVariableDecl;
|
||||
import com.sun.tools.javac.tree.JCTree.JCWildcard;
|
||||
import com.sun.tools.javac.tree.JCTree.TypeBoundKind;
|
||||
import com.sun.tools.javac.tree.TreeMaker;
|
||||
import com.sun.tools.javac.tree.TreeScanner;
|
||||
import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
|
||||
@@ -920,4 +927,71 @@ public class JavacHandlerUtil {
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a full clone of a given javac AST type node. Every part is cloned (every identifier, every select, every wildcard, every type apply).
|
||||
*
|
||||
* If there's any node in the tree that we don't know how to clone, that part isn't cloned. However, we wouldn't know what could possibly show up that we
|
||||
* can't currently clone; that's just a safeguard.
|
||||
*
|
||||
* This should be used if the type looks the same in the code, but resolves differently. For example, a static method that has some generics in it named after
|
||||
* the class's own parameter, but as its a static method, the static method's notion of {@code T} is different from the class notion of {@code T}. If you're duplicating
|
||||
* a type used in the class context, you need to use this method.
|
||||
*/
|
||||
public static JCExpression cloneType(TreeMaker maker, JCExpression in, JCTree source) {
|
||||
JCExpression out = cloneType0(maker, in);
|
||||
if (out != null) recursiveSetGeneratedBy(out, source);
|
||||
return out;
|
||||
}
|
||||
|
||||
private static JCExpression cloneType0(TreeMaker maker, JCTree in) {
|
||||
if (in == null) return null;
|
||||
|
||||
if (in instanceof JCPrimitiveTypeTree) return (JCExpression) in;
|
||||
|
||||
if (in instanceof JCIdent) {
|
||||
return maker.Ident(((JCIdent) in).name);
|
||||
}
|
||||
|
||||
if (in instanceof JCFieldAccess) {
|
||||
JCFieldAccess fa = (JCFieldAccess) in;
|
||||
return maker.Select(cloneType0(maker, fa.selected), fa.name);
|
||||
}
|
||||
|
||||
if (in instanceof JCArrayTypeTree) {
|
||||
JCArrayTypeTree att = (JCArrayTypeTree) in;
|
||||
return maker.TypeArray(cloneType0(maker, att.elemtype));
|
||||
}
|
||||
|
||||
if (in instanceof JCTypeApply) {
|
||||
JCTypeApply ta = (JCTypeApply) in;
|
||||
ListBuffer<JCExpression> lb = ListBuffer.lb();
|
||||
for (JCExpression typeArg : ta.arguments) {
|
||||
lb.append(cloneType0(maker, typeArg));
|
||||
}
|
||||
return maker.TypeApply(cloneType0(maker, ta.clazz), lb.toList());
|
||||
}
|
||||
|
||||
if (in instanceof JCWildcard) {
|
||||
JCWildcard w = (JCWildcard) in;
|
||||
JCExpression newInner = cloneType0(maker, w.inner);
|
||||
TypeBoundKind newKind;
|
||||
switch (w.getKind()) {
|
||||
case SUPER_WILDCARD:
|
||||
newKind = maker.TypeBoundKind(BoundKind.SUPER);
|
||||
break;
|
||||
case EXTENDS_WILDCARD:
|
||||
newKind = maker.TypeBoundKind(BoundKind.EXTENDS);
|
||||
break;
|
||||
default:
|
||||
case UNBOUNDED_WILDCARD:
|
||||
newKind = maker.TypeBoundKind(BoundKind.UNBOUND);
|
||||
break;
|
||||
}
|
||||
return maker.Wildcard(newKind, newInner);
|
||||
}
|
||||
|
||||
// This is somewhat unsafe, but it's better than outright throwing an exception here. Returning null will just cause an exception down the pipeline.
|
||||
return (JCExpression) in;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,4 +58,18 @@ class RequiredArgsConstructorStaticNameGenerics<T extends Number> {
|
||||
public static <T extends Number> RequiredArgsConstructorStaticNameGenerics<T> of(final T x) {
|
||||
return new RequiredArgsConstructorStaticNameGenerics<T>(x);
|
||||
}
|
||||
}
|
||||
class RequiredArgsConstructorStaticNameGenerics2<T extends Number> {
|
||||
final Class<T> x;
|
||||
String name;
|
||||
|
||||
@java.lang.SuppressWarnings("all")
|
||||
private RequiredArgsConstructorStaticNameGenerics2(final Class<T> x) {
|
||||
this.x = x;
|
||||
}
|
||||
|
||||
@java.lang.SuppressWarnings("all")
|
||||
public static <T extends Number> RequiredArgsConstructorStaticNameGenerics2<T> of(final Class<T> x) {
|
||||
return new RequiredArgsConstructorStaticNameGenerics2<T>(x);
|
||||
}
|
||||
}
|
||||
@@ -51,4 +51,15 @@
|
||||
public static @java.lang.SuppressWarnings("all") <T extends Number>RequiredArgsConstructorStaticNameGenerics<T> of(final T x) {
|
||||
return new RequiredArgsConstructorStaticNameGenerics<T>(x);
|
||||
}
|
||||
}
|
||||
@lombok.RequiredArgsConstructor(staticName = "of") class RequiredArgsConstructorStaticNameGenerics2<T extends Number> {
|
||||
final Class<T> x;
|
||||
String name;
|
||||
private @java.lang.SuppressWarnings("all") RequiredArgsConstructorStaticNameGenerics2(final Class<T> x) {
|
||||
super();
|
||||
this.x = x;
|
||||
}
|
||||
public static @java.lang.SuppressWarnings("all") <T extends Number>RequiredArgsConstructorStaticNameGenerics2<T> of(final Class<T> x) {
|
||||
return new RequiredArgsConstructorStaticNameGenerics2<T>(x);
|
||||
}
|
||||
}
|
||||
@@ -22,3 +22,7 @@
|
||||
final T x;
|
||||
String name;
|
||||
}
|
||||
@lombok.RequiredArgsConstructor(staticName="of") class RequiredArgsConstructorStaticNameGenerics2<T extends Number> {
|
||||
final Class<T> x;
|
||||
String name;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user