aboutsummaryrefslogtreecommitdiff
path: root/src/core
diff options
context:
space:
mode:
Diffstat (limited to 'src/core')
-rw-r--r--src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java11
-rw-r--r--src/core/lombok/eclipse/handlers/HandleConstructor.java15
-rw-r--r--src/core/lombok/javac/JavacResolution.java6
-rw-r--r--src/core/lombok/javac/handlers/HandleConstructor.java28
-rw-r--r--src/core/lombok/javac/handlers/HandleExtensionMethod.java6
-rw-r--r--src/core/lombok/javac/handlers/HandleSynchronized.java8
-rw-r--r--src/core/lombok/javac/handlers/JavacHandlerUtil.java102
7 files changed, 141 insertions, 35 deletions
diff --git a/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java b/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java
index 8b330816..ed18dd45 100644
--- a/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java
+++ b/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java
@@ -798,18 +798,19 @@ public class EclipseHandlerUtil {
}
}
- private static final Map<FieldDeclaration, GetterMethod> generatedLazyGetters = new WeakHashMap<FieldDeclaration, GetterMethod>();
+ private static final Map<FieldDeclaration, Object> generatedLazyGettersWithPrimitiveBoolean = new WeakHashMap<FieldDeclaration, Object>();
+ private static final Object MARKER = new Object();
static void registerCreatedLazyGetter(FieldDeclaration field, char[] methodName, TypeReference returnType) {
- generatedLazyGetters.put(field, new GetterMethod(methodName, returnType));
+ if (!nameEquals(returnType.getTypeName(), "boolean") || returnType.dimensions() > 0) return;
+ generatedLazyGettersWithPrimitiveBoolean.put(field, MARKER);
}
private static GetterMethod findGetter(EclipseNode field) {
FieldDeclaration fieldDeclaration = (FieldDeclaration) field.get();
- GetterMethod gm = generatedLazyGetters.get(fieldDeclaration);
- if (gm != null) return gm;
+ boolean forceBool = generatedLazyGettersWithPrimitiveBoolean.containsKey(fieldDeclaration);
TypeReference fieldType = fieldDeclaration.type;
- boolean isBoolean = nameEquals(fieldType.getTypeName(), "boolean") && fieldType.dimensions() == 0;
+ boolean isBoolean = forceBool || (nameEquals(fieldType.getTypeName(), "boolean") && fieldType.dimensions() == 0);
EclipseNode typeNode = field.up();
for (String potentialGetterName : toAllGetterNames(field, isBoolean)) {
diff --git a/src/core/lombok/eclipse/handlers/HandleConstructor.java b/src/core/lombok/eclipse/handlers/HandleConstructor.java
index eec41577..25d47870 100644
--- a/src/core/lombok/eclipse/handlers/HandleConstructor.java
+++ b/src/core/lombok/eclipse/handlers/HandleConstructor.java
@@ -156,20 +156,29 @@ public class HandleConstructor {
}
public void generateConstructor(EclipseNode typeNode, AccessLevel level, List<EclipseNode> fields, String staticName, boolean skipIfConstructorExists, boolean suppressConstructorProperties, ASTNode source) {
+ boolean staticConstrRequired = staticName != null && !staticName.equals("");
+
if (skipIfConstructorExists && constructorExists(typeNode) != MemberExistsResult.NOT_EXISTS) return;
if (skipIfConstructorExists) {
for (EclipseNode child : typeNode.down()) {
if (child.getKind() == Kind.ANNOTATION) {
if (annotationTypeMatches(NoArgsConstructor.class, child) ||
annotationTypeMatches(AllArgsConstructor.class, child) ||
- annotationTypeMatches(RequiredArgsConstructor.class, child))
+ annotationTypeMatches(RequiredArgsConstructor.class, child)) {
+
+ if (staticConstrRequired) {
+ // @Data has asked us to generate a constructor, but we're going to skip this instruction, as an explicit 'make a constructor' annotation
+ // will take care of it. However, @Data also wants a specific static name; this will be ignored; the appropriate way to do this is to use
+ // the 'staticName' parameter of the @XArgsConstructor you've stuck on your type.
+ // We should warn that we're ignoring @Data's 'staticConstructor' param.
+ typeNode.addWarning("Ignoring static constructor name: explicit @XxxArgsConstructor annotation present; its `staticName` parameter will be used.", source.sourceStart, source.sourceEnd);
+ }
return;
+ }
}
}
}
- boolean staticConstrRequired = staticName != null && !staticName.equals("");
-
ConstructorDeclaration constr = createConstructor(staticConstrRequired ? AccessLevel.PRIVATE : level, typeNode, fields, suppressConstructorProperties, source);
injectMethod(typeNode, constr);
if (staticConstrRequired) {
diff --git a/src/core/lombok/javac/JavacResolution.java b/src/core/lombok/javac/JavacResolution.java
index 6da60907..73bb38b0 100644
--- a/src/core/lombok/javac/JavacResolution.java
+++ b/src/core/lombok/javac/JavacResolution.java
@@ -456,12 +456,18 @@ public class JavacResolution {
if (upper == null || upper.toString().equals("java.lang.Object")) {
return maker.Wildcard(maker.TypeBoundKind(BoundKind.UNBOUND), null);
}
+ 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));
} else {
return maker.Wildcard(maker.TypeBoundKind(BoundKind.SUPER), typeToJCTree(lower, ast, false, false));
}
}
if (upper != null) {
+ if (upper.getTypeArguments().contains(type)) {
+ return maker.Wildcard(maker.TypeBoundKind(BoundKind.UNBOUND), null);
+ }
return typeToJCTree(upper, ast, allowCompound, allowVoid);
}
diff --git a/src/core/lombok/javac/handlers/HandleConstructor.java b/src/core/lombok/javac/handlers/HandleConstructor.java
index a2463728..d701b41e 100644
--- a/src/core/lombok/javac/handlers/HandleConstructor.java
+++ b/src/core/lombok/javac/handlers/HandleConstructor.java
@@ -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;
@@ -154,20 +152,29 @@ public class HandleConstructor {
}
public void generateConstructor(JavacNode typeNode, AccessLevel level, List<JavacNode> fields, String staticName, boolean skipIfConstructorExists, boolean suppressConstructorProperties, JavacNode source) {
+ boolean staticConstrRequired = staticName != null && !staticName.equals("");
+
if (skipIfConstructorExists && constructorExists(typeNode) != MemberExistsResult.NOT_EXISTS) return;
if (skipIfConstructorExists) {
for (JavacNode child : typeNode.down()) {
if (child.getKind() == Kind.ANNOTATION) {
if (annotationTypeMatches(NoArgsConstructor.class, child) ||
annotationTypeMatches(AllArgsConstructor.class, child) ||
- annotationTypeMatches(RequiredArgsConstructor.class, child))
+ annotationTypeMatches(RequiredArgsConstructor.class, child)) {
+
+ if (staticConstrRequired) {
+ // @Data has asked us to generate a constructor, but we're going to skip this instruction, as an explicit 'make a constructor' annotation
+ // will take care of it. However, @Data also wants a specific static name; this will be ignored; the appropriate way to do this is to use
+ // the 'staticName' parameter of the @XArgsConstructor you've stuck on your type.
+ // We should warn that we're ignoring @Data's 'staticConstructor' param.
+ source.addWarning("Ignoring static constructor name: explicit @XxxArgsConstructor annotation present; its `staticName` parameter will be used.");
+ }
return;
+ }
}
}
}
- boolean staticConstrRequired = staticName != null && !staticName.equals("");
-
JCMethodDecl constr = createConstructor(staticConstrRequired ? AccessLevel.PRIVATE : level, typeNode, fields, suppressConstructorProperties, source.get());
injectMethod(typeNode, constr);
if (staticConstrRequired) {
@@ -259,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);
diff --git a/src/core/lombok/javac/handlers/HandleExtensionMethod.java b/src/core/lombok/javac/handlers/HandleExtensionMethod.java
index 2df6be45..92d7c0e4 100644
--- a/src/core/lombok/javac/handlers/HandleExtensionMethod.java
+++ b/src/core/lombok/javac/handlers/HandleExtensionMethod.java
@@ -55,7 +55,6 @@ 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.JCMethodInvocation;
-import com.sun.tools.javac.tree.TreeMaker;
/**
* Handles the {@link ExtensionMethod} annotation for javac.
@@ -180,10 +179,7 @@ public class HandleExtensionMethod extends JavacAnnotationHandler<ExtensionMetho
Type firstArgType = types.erasure(extensionMethodType.asMethodType().argtypes.get(0));
if (!types.isAssignable(receiverType, firstArgType)) continue;
methodCall.args = methodCall.args.prepend(receiver);
-
- TreeMaker maker = annotationNode.getTreeMaker();
- JCIdent extensionClassIdent = maker.Ident(annotationNode.toName(extensionProvider.toString()));
- methodCall.meth = maker.Select(extensionClassIdent, annotationNode.toName(methodName));
+ methodCall.meth = chainDotsString(annotationNode, extensionProvider.toString() + "." + methodName);
return;
}
}
diff --git a/src/core/lombok/javac/handlers/HandleSynchronized.java b/src/core/lombok/javac/handlers/HandleSynchronized.java
index 04668317..1ba8d131 100644
--- a/src/core/lombok/javac/handlers/HandleSynchronized.java
+++ b/src/core/lombok/javac/handlers/HandleSynchronized.java
@@ -78,16 +78,16 @@ public class HandleSynchronized extends JavacAnnotationHandler<Synchronized> {
lockName = isStatic ? STATIC_LOCK_NAME : INSTANCE_LOCK_NAME;
}
- TreeMaker maker = methodNode.getTreeMaker();
+ TreeMaker maker = methodNode.getTreeMaker().at(ast.pos);
if (fieldExists(lockName, methodNode) == MemberExistsResult.NOT_EXISTS) {
if (!autoMake) {
annotationNode.addError("The field " + lockName + " does not exist.");
return;
}
- JCExpression objectType = chainDots(methodNode, "java", "lang", "Object");
+ JCExpression objectType = chainDots(methodNode, ast.pos, "java", "lang", "Object");
//We use 'new Object[0];' because unlike 'new Object();', empty arrays *ARE* serializable!
- JCNewArray newObjectArray = maker.NewArray(chainDots(methodNode, "java", "lang", "Object"),
+ JCNewArray newObjectArray = maker.NewArray(chainDots(methodNode, ast.pos, "java", "lang", "Object"),
List.<JCExpression>of(maker.Literal(Javac.getCtcInt(TypeTags.class, "INT"), 0)), null);
JCVariableDecl fieldDecl = recursiveSetGeneratedBy(maker.VarDef(
maker.Modifiers(Flags.PRIVATE | Flags.FINAL | (isStatic ? Flags.STATIC : 0)),
@@ -99,7 +99,7 @@ public class HandleSynchronized extends JavacAnnotationHandler<Synchronized> {
JCExpression lockNode;
if (isStatic) {
- lockNode = chainDots(methodNode, methodNode.up().getName(), lockName);
+ lockNode = chainDots(methodNode, ast.pos, methodNode.up().getName(), lockName);
} else {
lockNode = maker.Select(maker.Ident(methodNode.toName("this")), methodNode.toName(lockName));
}
diff --git a/src/core/lombok/javac/handlers/JavacHandlerUtil.java b/src/core/lombok/javac/handlers/JavacHandlerUtil.java
index f2cdee6d..b0f2a890 100644
--- a/src/core/lombok/javac/handlers/JavacHandlerUtil.java
+++ b/src/core/lombok/javac/handlers/JavacHandlerUtil.java
@@ -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,9 +63,13 @@ 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.JCTypeParameter;
+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;
@@ -244,6 +251,7 @@ public class JavacHandlerUtil {
* Only does this if the DeleteLombokAnnotations class is in the context.
*/
public static void deleteAnnotationIfNeccessary(JavacNode annotation, Class<? extends Annotation> annotationType) {
+ if (inNetbeansEditor(annotation)) return;
if (!annotation.shouldDeleteLombokAnnotations()) return;
JavacNode parentNode = annotation.directUp();
switch (parentNode.getKind()) {
@@ -274,6 +282,7 @@ public class JavacHandlerUtil {
}
public static void deleteImportFromCompilationUnit(JavacNode node, String name) {
+ if (inNetbeansEditor(node)) return;
if (!node.shouldDeleteLombokAnnotations()) return;
ListBuffer<JCTree> newDefs = ListBuffer.lb();
@@ -768,6 +777,8 @@ public class JavacHandlerUtil {
* In javac, dotted access of any kind, from {@code java.lang.String} to {@code var.methodName}
* is represented by a fold-left of {@code Select} nodes with the leftmost string represented by
* a {@code Ident} node. This method generates such an expression.
+ * <p>
+ * The position of the generated node(s) will be unpositioned (-1).
*
* For example, maker.Select(maker.Select(maker.Ident(NAME[java]), NAME[lang]), NAME[String]).
*
@@ -775,12 +786,30 @@ public class JavacHandlerUtil {
* @see com.sun.tools.javac.tree.JCTree.JCFieldAccess
*/
public static JCExpression chainDots(JavacNode node, String... elems) {
+ return chainDots(node, -1, elems);
+ }
+
+ /**
+ * In javac, dotted access of any kind, from {@code java.lang.String} to {@code var.methodName}
+ * is represented by a fold-left of {@code Select} nodes with the leftmost string represented by
+ * a {@code Ident} node. This method generates such an expression.
+ * <p>
+ * The position of the generated node(s) will be equal to the {@code pos} parameter.
+ *
+ * For example, maker.Select(maker.Select(maker.Ident(NAME[java]), NAME[lang]), NAME[String]).
+ *
+ * @see com.sun.tools.javac.tree.JCTree.JCIdent
+ * @see com.sun.tools.javac.tree.JCTree.JCFieldAccess
+ */
+ public static JCExpression chainDots(JavacNode node, int pos, String... elems) {
assert elems != null;
assert elems.length > 0;
- JCExpression e = node.getTreeMaker().Ident(node.toName(elems[0]));
+ TreeMaker maker = node.getTreeMaker();
+ if (pos != -1) maker = maker.at(pos);
+ JCExpression e = maker.Ident(node.toName(elems[0]));
for (int i = 1 ; i < elems.length ; i++) {
- e = node.getTreeMaker().Select(e, node.toName(elems[i]));
+ e = maker.Select(e, node.toName(elems[i]));
}
return e;
@@ -798,7 +827,7 @@ public class JavacHandlerUtil {
* @see com.sun.tools.javac.tree.JCTree.JCFieldAccess
*/
public static JCExpression chainDotsString(JavacNode node, String elems) {
- return chainDots(node, elems.split("\\."));
+ return chainDots(node, elems.split("\\."));
}
/**
@@ -922,4 +951,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;
+ }
}