aboutsummaryrefslogtreecommitdiff
path: root/src/core/lombok/javac
diff options
context:
space:
mode:
authorReinier Zwitserloot <r.zwitserloot@projectlombok.org>2021-03-22 08:03:42 +0100
committerReinier Zwitserloot <r.zwitserloot@projectlombok.org>2021-03-22 08:03:42 +0100
commitbcd05a01b14705678dfd280989fa5071b627a234 (patch)
tree55f5af9b2b158c37f9d04b7ec27aad048d4e1ffd /src/core/lombok/javac
parentade900b82b8205bb439ac9d6d99dff0c3af6e10f (diff)
parentfa0b5249cf5fee28d9be13ecdf0225f651f686aa (diff)
downloadlombok-bcd05a01b14705678dfd280989fa5071b627a234.tar.gz
lombok-bcd05a01b14705678dfd280989fa5071b627a234.tar.bz2
lombok-bcd05a01b14705678dfd280989fa5071b627a234.zip
Merge branch 'records'
# Conflicts: # src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java # src/core/lombok/eclipse/handlers/HandleBuilder.java # src/core/lombok/eclipse/handlers/HandleData.java # src/core/lombok/eclipse/handlers/HandleNonNull.java # src/core/lombok/eclipse/handlers/HandleSuperBuilder.java # src/core/lombok/javac/handlers/HandleBuilder.java # src/core/lombok/javac/handlers/HandleNonNull.java # src/core/lombok/javac/handlers/HandleSuperBuilder.java # test/core/src/lombok/RunTestsViaEcj.java
Diffstat (limited to 'src/core/lombok/javac')
-rw-r--r--src/core/lombok/javac/JavacNode.java12
-rw-r--r--src/core/lombok/javac/handlers/HandleBuilder.java15
-rw-r--r--src/core/lombok/javac/handlers/HandleConstructor.java7
-rw-r--r--src/core/lombok/javac/handlers/HandleData.java3
-rw-r--r--src/core/lombok/javac/handlers/HandleEqualsAndHashCode.java12
-rw-r--r--src/core/lombok/javac/handlers/HandleFieldDefaults.java7
-rw-r--r--src/core/lombok/javac/handlers/HandleGetter.java14
-rw-r--r--src/core/lombok/javac/handlers/HandleLog.java17
-rw-r--r--src/core/lombok/javac/handlers/HandleNonNull.java12
-rw-r--r--src/core/lombok/javac/handlers/HandleSetter.java13
-rw-r--r--src/core/lombok/javac/handlers/HandleSuperBuilder.java7
-rw-r--r--src/core/lombok/javac/handlers/HandleSynchronized.java8
-rw-r--r--src/core/lombok/javac/handlers/HandleToString.java8
-rw-r--r--src/core/lombok/javac/handlers/HandleUtilityClass.java9
-rw-r--r--src/core/lombok/javac/handlers/HandleWithBy.java3
-rw-r--r--src/core/lombok/javac/handlers/JavacHandlerUtil.java53
16 files changed, 116 insertions, 84 deletions
diff --git a/src/core/lombok/javac/JavacNode.java b/src/core/lombok/javac/JavacNode.java
index 3de3f38b..035f7c53 100644
--- a/src/core/lombok/javac/JavacNode.java
+++ b/src/core/lombok/javac/JavacNode.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009-2020 The Project Lombok Authors.
+ * Copyright (C) 2009-2021 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
@@ -186,16 +186,6 @@ public class JavacNode extends lombok.core.LombokNode<JavacAST, JavacNode, JCTre
return false;
}
- @Override protected boolean fieldContainsAnnotation(JCTree field, JCTree annotation) {
- if (!(field instanceof JCVariableDecl)) return false;
- JCVariableDecl f = (JCVariableDecl) field;
- if (f.mods.annotations == null) return false;
- for (JCAnnotation childAnnotation : f.mods.annotations) {
- if (childAnnotation == annotation) return true;
- }
- return false;
- }
-
/**
* Convenient shortcut to the owning JavacAST object's getTreeMaker method.
*
diff --git a/src/core/lombok/javac/handlers/HandleBuilder.java b/src/core/lombok/javac/handlers/HandleBuilder.java
index 911a2e39..a25baeb0 100644
--- a/src/core/lombok/javac/handlers/HandleBuilder.java
+++ b/src/core/lombok/javac/handlers/HandleBuilder.java
@@ -192,6 +192,8 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> {
}
@Override public void handle(AnnotationValues<Builder> annotation, JCAnnotation ast, JavacNode annotationNode) {
+ final String BUILDER_NODE_NOT_SUPPORTED_ERR = "@Builder is only supported on classes, records, constructors, and methods.";
+
handleFlagUsage(annotationNode, ConfigurationKeys.BUILDER_FLAG_USAGE, "@Builder");
BuilderJob job = new BuilderJob();
job.sourceNode = annotationNode;
@@ -229,6 +231,11 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> {
ArrayList<JavacNode> nonFinalNonDefaultedFields = null;
if (parent.get() instanceof JCClassDecl) {
+ if (!isClass(parent) && !isRecord(parent)) {
+ annotationNode.addError(BUILDER_NODE_NOT_SUPPORTED_ERR);
+ return;
+ }
+
job.parentType = parent;
JCClassDecl td = (JCClassDecl) parent.get();
@@ -279,7 +286,11 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> {
allFields.append(fieldNode);
}
- handleConstructor.generateConstructor(parent, AccessLevel.PACKAGE, List.<JCAnnotation>nil(), allFields.toList(), false, null, SkipIfConstructorExists.I_AM_BUILDER, annotationNode);
+ if (!isRecord(parent)) {
+ // Records ship with a canonical constructor that acts as @AllArgsConstructor - just use that one.
+
+ handleConstructor.generateConstructor(parent, AccessLevel.PACKAGE, List.<JCAnnotation>nil(), allFields.toList(), false, null, SkipIfConstructorExists.I_AM_BUILDER, annotationNode);
+ }
buildMethodReturnType = namePlusTypeParamsToTypeReference(parent.getTreeMaker(), parent, td.typarams);
job.typeParams = job.builderTypeParams = td.typarams;
@@ -387,7 +398,7 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> {
}
}
} else {
- annotationNode.addError("@Builder is only supported on types, constructors, and methods.");
+ annotationNode.addError(BUILDER_NODE_NOT_SUPPORTED_ERR);
return;
}
diff --git a/src/core/lombok/javac/handlers/HandleConstructor.java b/src/core/lombok/javac/handlers/HandleConstructor.java
index 0defdefd..9c74ca0e 100644
--- a/src/core/lombok/javac/handlers/HandleConstructor.java
+++ b/src/core/lombok/javac/handlers/HandleConstructor.java
@@ -181,12 +181,7 @@ public class HandleConstructor {
}
public static boolean checkLegality(JavacNode typeNode, JavacNode errorNode, String name) {
- JCClassDecl typeDecl = null;
- if (typeNode.get() instanceof JCClassDecl) typeDecl = (JCClassDecl) typeNode.get();
- long modifiers = typeDecl == null ? 0 : typeDecl.mods.flags;
- boolean notAClass = (modifiers & (Flags.INTERFACE | Flags.ANNOTATION)) != 0;
-
- if (typeDecl == null || notAClass) {
+ if (!isClassOrEnum(typeNode)) {
errorNode.addError(name + " is only supported on a class or an enum.");
return false;
}
diff --git a/src/core/lombok/javac/handlers/HandleData.java b/src/core/lombok/javac/handlers/HandleData.java
index 5fe1e4fe..06524aa8 100644
--- a/src/core/lombok/javac/handlers/HandleData.java
+++ b/src/core/lombok/javac/handlers/HandleData.java
@@ -51,9 +51,8 @@ public class HandleData extends JavacAnnotationHandler<Data> {
deleteAnnotationIfNeccessary(annotationNode, Data.class);
JavacNode typeNode = annotationNode.up();
- boolean notAClass = !isClass(typeNode);
- if (notAClass) {
+ if (!isClass(typeNode)) {
annotationNode.addError("@Data is only supported on a class.");
return;
}
diff --git a/src/core/lombok/javac/handlers/HandleEqualsAndHashCode.java b/src/core/lombok/javac/handlers/HandleEqualsAndHashCode.java
index a75d551f..ffe882d8 100644
--- a/src/core/lombok/javac/handlers/HandleEqualsAndHashCode.java
+++ b/src/core/lombok/javac/handlers/HandleEqualsAndHashCode.java
@@ -95,9 +95,9 @@ public class HandleEqualsAndHashCode extends JavacAnnotationHandler<EqualsAndHas
Boolean doNotUseGettersConfiguration = annotationNode.getAst().readConfiguration(ConfigurationKeys.EQUALS_AND_HASH_CODE_DO_NOT_USE_GETTERS);
boolean doNotUseGetters = annotation.isExplicit("doNotUseGetters") || doNotUseGettersConfiguration == null ? ann.doNotUseGetters() : doNotUseGettersConfiguration;
FieldAccess fieldAccess = doNotUseGetters ? FieldAccess.PREFER_FIELD : FieldAccess.GETTER;
-
+
boolean cacheHashCode = ann.cacheStrategy() == CacheStrategy.LAZY;
-
+
generateMethods(typeNode, annotationNode, members, callSuper, true, cacheHashCode, fieldAccess, onParam);
}
@@ -118,13 +118,7 @@ public class HandleEqualsAndHashCode extends JavacAnnotationHandler<EqualsAndHas
public void generateMethods(JavacNode typeNode, JavacNode source, java.util.List<Included<JavacNode, EqualsAndHashCode.Include>> members,
Boolean callSuper, boolean whineIfExists, boolean cacheHashCode, FieldAccess fieldAccess, List<JCAnnotation> onParam) {
- boolean notAClass = true;
- if (typeNode.get() instanceof JCClassDecl) {
- long flags = ((JCClassDecl) typeNode.get()).mods.flags;
- notAClass = (flags & (Flags.INTERFACE | Flags.ANNOTATION | Flags.ENUM)) != 0;
- }
-
- if (notAClass) {
+ if (!isClass(typeNode)) {
source.addError("@EqualsAndHashCode is only supported on a class.");
return;
}
diff --git a/src/core/lombok/javac/handlers/HandleFieldDefaults.java b/src/core/lombok/javac/handlers/HandleFieldDefaults.java
index 4a87c138..ebab67e3 100644
--- a/src/core/lombok/javac/handlers/HandleFieldDefaults.java
+++ b/src/core/lombok/javac/handlers/HandleFieldDefaults.java
@@ -56,12 +56,7 @@ public class HandleFieldDefaults extends JavacASTAdapter {
}
}
- JCClassDecl typeDecl = null;
- if (typeNode.get() instanceof JCClassDecl) typeDecl = (JCClassDecl) typeNode.get();
- long modifiers = typeDecl == null ? 0 : typeDecl.mods.flags;
- boolean notAClass = (modifiers & (Flags.INTERFACE | Flags.ANNOTATION)) != 0;
-
- if (typeDecl == null || notAClass) {
+ if (!isClassOrEnum(typeNode)) {
errorNode.addError("@FieldDefaults is only supported on a class or an enum.");
return false;
}
diff --git a/src/core/lombok/javac/handlers/HandleGetter.java b/src/core/lombok/javac/handlers/HandleGetter.java
index 4cfa3276..8f6de9bb 100644
--- a/src/core/lombok/javac/handlers/HandleGetter.java
+++ b/src/core/lombok/javac/handlers/HandleGetter.java
@@ -51,7 +51,6 @@ import com.sun.tools.javac.tree.JCTree;
import com.sun.tools.javac.tree.JCTree.JCAnnotation;
import com.sun.tools.javac.tree.JCTree.JCBinary;
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.JCExpressionStatement;
import com.sun.tools.javac.tree.JCTree.JCIf;
@@ -72,6 +71,8 @@ import com.sun.tools.javac.util.Name;
*/
@Provides
public class HandleGetter extends JavacAnnotationHandler<Getter> {
+ private static final String GETTER_NODE_NOT_SUPPORTED_ERR = "@Getter is only supported on a class, an enum, or a field.";
+
public void generateGetterForType(JavacNode typeNode, JavacNode errorNode, AccessLevel level, boolean checkForTypeLevelGetter, List<JCAnnotation> onMethod) {
if (checkForTypeLevelGetter) {
if (hasAnnotation(Getter.class, typeNode)) {
@@ -80,13 +81,8 @@ public class HandleGetter extends JavacAnnotationHandler<Getter> {
}
}
- JCClassDecl typeDecl = null;
- if (typeNode.get() instanceof JCClassDecl) typeDecl = (JCClassDecl) typeNode.get();
- long modifiers = typeDecl == null ? 0 : typeDecl.mods.flags;
- boolean notAClass = (modifiers & (Flags.INTERFACE | Flags.ANNOTATION)) != 0;
-
- if (typeDecl == null || notAClass) {
- errorNode.addError("@Getter is only supported on a class, an enum, or a field.");
+ if (!isClassOrEnum(typeNode)) {
+ errorNode.addError(GETTER_NODE_NOT_SUPPORTED_ERR);
return;
}
@@ -170,7 +166,7 @@ public class HandleGetter extends JavacAnnotationHandler<Getter> {
JavacNode fieldNode, JavacNode source, boolean whineIfExists, boolean lazy, List<JCAnnotation> onMethod) {
if (fieldNode.getKind() != Kind.FIELD) {
- source.addError("@Getter is only supported on a class or a field.");
+ source.addError(GETTER_NODE_NOT_SUPPORTED_ERR);
return;
}
diff --git a/src/core/lombok/javac/handlers/HandleLog.java b/src/core/lombok/javac/handlers/HandleLog.java
index 674aa62c..47c4098f 100644
--- a/src/core/lombok/javac/handlers/HandleLog.java
+++ b/src/core/lombok/javac/handlers/HandleLog.java
@@ -31,6 +31,7 @@ import lombok.core.configuration.IdentifierName;
import lombok.core.configuration.LogDeclaration;
import lombok.core.configuration.LogDeclaration.LogFactoryParameter;
import lombok.core.handlers.LoggingFramework;
+import lombok.javac.Javac;
import lombok.javac.JavacAnnotationHandler;
import lombok.javac.JavacNode;
import lombok.javac.JavacTreeMaker;
@@ -74,9 +75,14 @@ public class HandleLog {
return;
}
+ if (isRecord(typeNode) && !useStatic) {
+ annotationNode.addError("Logger fields must be static in records.");
+ return;
+ }
+
Object valueGuess = annotation.getValueGuess("topic");
JCExpression loggerTopic = (JCExpression) annotation.getActualExpression("topic");
-
+
if (valueGuess instanceof String && ((String) valueGuess).trim().isEmpty()) loggerTopic = null;
if (framework.getDeclaration().getParametersWithTopic() == null && loggerTopic != null) {
annotationNode.addError(framework.getAnnotationAsString() + " does not allow a topic.");
@@ -118,7 +124,14 @@ public class HandleLog {
maker.Modifiers(Flags.PRIVATE | Flags.FINAL | (useStatic ? Flags.STATIC : 0)),
typeNode.toName(logFieldName), loggerType, factoryMethodCall), source);
- injectFieldAndMarkGenerated(typeNode, fieldDecl);
+ if (isRecord(typeNode) && Javac.getJavaCompilerVersion() < 16) {
+ // This is a workaround for https://bugs.openjdk.java.net/browse/JDK-8243057
+
+ injectField(typeNode, fieldDecl);
+ } else {
+ injectFieldAndMarkGenerated(typeNode, fieldDecl);
+ }
+
return true;
}
diff --git a/src/core/lombok/javac/handlers/HandleNonNull.java b/src/core/lombok/javac/handlers/HandleNonNull.java
index 174c31de..2f359c0f 100644
--- a/src/core/lombok/javac/handlers/HandleNonNull.java
+++ b/src/core/lombok/javac/handlers/HandleNonNull.java
@@ -49,6 +49,7 @@ import com.sun.tools.javac.tree.JCTree.JCVariableDecl;
import com.sun.tools.javac.util.List;
import com.sun.tools.javac.util.Name;
+import lombok.AccessLevel;
import lombok.ConfigurationKeys;
import lombok.NonNull;
import lombok.core.AST.Kind;
@@ -56,11 +57,14 @@ import lombok.core.AnnotationValues;
import lombok.core.HandlerPriority;
import lombok.javac.JavacAnnotationHandler;
import lombok.javac.JavacNode;
+import lombok.javac.handlers.HandleConstructor.SkipIfConstructorExists;
import lombok.spi.Provides;
@Provides
@HandlerPriority(value = 512) // 2^9; onParameter=@__(@NonNull) has to run first.
public class HandleNonNull extends JavacAnnotationHandler<NonNull> {
+ private HandleConstructor handleConstructor = new HandleConstructor();
+
@Override public void handle(AnnotationValues<NonNull> annotation, JCAnnotation ast, JavacNode annotationNode) {
handleFlagUsage(annotationNode, ConfigurationKeys.NON_NULL_FLAG_USAGE, "@NonNull");
@@ -122,6 +126,14 @@ public class HandleNonNull extends JavacAnnotationHandler<NonNull> {
String expectedName = paramNode.getName();
+ JavacNode typeNode = upToTypeNode(annotationNode);
+
+ if ((declaration.mods.flags & RECORD) != 0) {
+ if (!lombokConstructorExists(typeNode)) {
+ handleConstructor.generateAllArgsConstructor(typeNode, AccessLevel.PUBLIC, null, SkipIfConstructorExists.NO, annotationNode);
+ }
+ }
+
/* Abort if the null check is already there, delving into try and synchronized statements */ {
List<JCStatement> stats = statements;
int idx = 0;
diff --git a/src/core/lombok/javac/handlers/HandleSetter.java b/src/core/lombok/javac/handlers/HandleSetter.java
index a4fb1b71..5c34f9f5 100644
--- a/src/core/lombok/javac/handlers/HandleSetter.java
+++ b/src/core/lombok/javac/handlers/HandleSetter.java
@@ -61,6 +61,8 @@ import com.sun.tools.javac.util.Name;
*/
@Provides
public class HandleSetter extends JavacAnnotationHandler<Setter> {
+ private static final String SETTER_NODE_NOT_SUPPORTED_ERR = "@Setter is only supported on a class or a field.";
+
public void generateSetterForType(JavacNode typeNode, JavacNode errorNode, AccessLevel level, boolean checkForTypeLevelSetter, List<JCAnnotation> onMethod, List<JCAnnotation> onParam) {
if (checkForTypeLevelSetter) {
if (hasAnnotation(Setter.class, typeNode)) {
@@ -69,13 +71,8 @@ public class HandleSetter extends JavacAnnotationHandler<Setter> {
}
}
- JCClassDecl typeDecl = null;
- if (typeNode.get() instanceof JCClassDecl) typeDecl = (JCClassDecl) typeNode.get();
- long modifiers = typeDecl == null ? 0 : typeDecl.mods.flags;
- boolean notAClass = (modifiers & (Flags.INTERFACE | Flags.ANNOTATION | Flags.ENUM)) != 0;
-
- if (typeDecl == null || notAClass) {
- errorNode.addError("@Setter is only supported on a class or a field.");
+ if (!isClass(typeNode)) {
+ errorNode.addError(SETTER_NODE_NOT_SUPPORTED_ERR);
return;
}
@@ -149,7 +146,7 @@ public class HandleSetter extends JavacAnnotationHandler<Setter> {
public void createSetterForField(AccessLevel level, JavacNode fieldNode, JavacNode sourceNode, boolean whineIfExists, List<JCAnnotation> onMethod, List<JCAnnotation> onParam) {
if (fieldNode.getKind() != Kind.FIELD) {
- fieldNode.addError("@Setter is only supported on a class or a field.");
+ fieldNode.addError(SETTER_NODE_NOT_SUPPORTED_ERR);
return;
}
diff --git a/src/core/lombok/javac/handlers/HandleSuperBuilder.java b/src/core/lombok/javac/handlers/HandleSuperBuilder.java
index 17b54f3c..9185cedf 100644
--- a/src/core/lombok/javac/handlers/HandleSuperBuilder.java
+++ b/src/core/lombok/javac/handlers/HandleSuperBuilder.java
@@ -159,14 +159,15 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> {
List<JCExpression> superclassTypeParams = List.nil();
boolean addCleaning = false;
- if (!(parent.get() instanceof JCClassDecl)) {
- annotationNode.addError("@SuperBuilder is only supported on types.");
+ if (!isClass(parent)) {
+ annotationNode.addError("@SuperBuilder is only supported on classes.");
return;
}
- // Gather all fields of the class that should be set by the builder.
job.parentType = parent;
JCClassDecl td = (JCClassDecl) parent.get();
+
+ // Gather all fields of the class that should be set by the builder.
ArrayList<JavacNode> nonFinalNonDefaultedFields = null;
boolean valuePresent = (hasAnnotation(lombok.Value.class, parent) || hasAnnotation("lombok.experimental.Value", parent));
diff --git a/src/core/lombok/javac/handlers/HandleSynchronized.java b/src/core/lombok/javac/handlers/HandleSynchronized.java
index ca4a8293..0bf7cbe8 100644
--- a/src/core/lombok/javac/handlers/HandleSynchronized.java
+++ b/src/core/lombok/javac/handlers/HandleSynchronized.java
@@ -76,6 +76,12 @@ public class HandleSynchronized extends JavacAnnotationHandler<Synchronized> {
return;
}
+ JavacNode typeNode = upToTypeNode(annotationNode);
+ if (!isClassOrEnum(typeNode)) {
+ annotationNode.addError("@Synchronized is legal only on methods in classes and enums.");
+ return;
+ }
+
boolean[] isStatic = new boolean[] {(method.mods.flags & Flags.STATIC) != 0};
String lockName = annotation.getInstance().value();
boolean autoMake = false;
@@ -86,8 +92,6 @@ public class HandleSynchronized extends JavacAnnotationHandler<Synchronized> {
JavacTreeMaker maker = methodNode.getTreeMaker().at(ast.pos);
- JavacNode typeNode = upToTypeNode(annotationNode);
-
MemberExistsResult exists = MemberExistsResult.NOT_EXISTS;
if (typeNode != null && typeNode.get() instanceof JCClassDecl) {
diff --git a/src/core/lombok/javac/handlers/HandleToString.java b/src/core/lombok/javac/handlers/HandleToString.java
index 1b76285f..3fc6a4e4 100644
--- a/src/core/lombok/javac/handlers/HandleToString.java
+++ b/src/core/lombok/javac/handlers/HandleToString.java
@@ -105,13 +105,7 @@ public class HandleToString extends JavacAnnotationHandler<ToString> {
public void generateToString(JavacNode typeNode, JavacNode source, java.util.List<Included<JavacNode, ToString.Include>> members,
boolean includeFieldNames, Boolean callSuper, boolean whineIfExists, FieldAccess fieldAccess) {
- boolean notAClass = true;
- if (typeNode.get() instanceof JCClassDecl) {
- long flags = ((JCClassDecl) typeNode.get()).mods.flags;
- notAClass = (flags & (Flags.INTERFACE | Flags.ANNOTATION)) != 0;
- }
-
- if (notAClass) {
+ if (!isClassOrEnum(typeNode)) {
source.addError("@ToString is only supported on a class or enum.");
return;
}
diff --git a/src/core/lombok/javac/handlers/HandleUtilityClass.java b/src/core/lombok/javac/handlers/HandleUtilityClass.java
index cb8a72ad..e006cc47 100644
--- a/src/core/lombok/javac/handlers/HandleUtilityClass.java
+++ b/src/core/lombok/javac/handlers/HandleUtilityClass.java
@@ -67,13 +67,8 @@ public class HandleUtilityClass extends JavacAnnotationHandler<UtilityClass> {
}
private static boolean checkLegality(JavacNode typeNode, JavacNode errorNode) {
- JCClassDecl typeDecl = null;
- if (typeNode.get() instanceof JCClassDecl) typeDecl = (JCClassDecl) typeNode.get();
- long modifiers = typeDecl == null ? 0 : typeDecl.mods.flags;
- boolean notAClass = (modifiers & (Flags.INTERFACE | Flags.ANNOTATION | Flags.ENUM)) != 0;
-
- if (typeDecl == null || notAClass) {
- errorNode.addError("@UtilityClass is only supported on a class (can't be an interface, enum, or annotation).");
+ if (!isClass(typeNode)) {
+ errorNode.addError("@UtilityClass is only supported on a class.");
return false;
}
diff --git a/src/core/lombok/javac/handlers/HandleWithBy.java b/src/core/lombok/javac/handlers/HandleWithBy.java
index b88f2c14..f1f953b3 100644
--- a/src/core/lombok/javac/handlers/HandleWithBy.java
+++ b/src/core/lombok/javac/handlers/HandleWithBy.java
@@ -125,7 +125,6 @@ public class HandleWithBy extends JavacAnnotationHandler<WithBy> {
@Override public void handle(AnnotationValues<WithBy> annotation, JCAnnotation ast, JavacNode annotationNode) {
handleExperimentalFlagUsage(annotationNode, ConfigurationKeys.WITHBY_FLAG_USAGE, "@WithBy");
- Collection<JavacNode> fields = annotationNode.upFromAnnotationToFields();
deleteAnnotationIfNeccessary(annotationNode, WithBy.class);
deleteImportFromCompilationUnit(annotationNode, "lombok.AccessLevel");
JavacNode node = annotationNode.up();
@@ -137,7 +136,7 @@ public class HandleWithBy extends JavacAnnotationHandler<WithBy> {
switch (node.getKind()) {
case FIELD:
- createWithByForFields(level, fields, annotationNode, true, onMethod);
+ createWithByForFields(level, annotationNode.upFromAnnotationToFields(), annotationNode, true, onMethod);
break;
case TYPE:
if (!onMethod.isEmpty()) annotationNode.addError("'onMethod' is not supported for @WithBy on a type.");
diff --git a/src/core/lombok/javac/handlers/JavacHandlerUtil.java b/src/core/lombok/javac/handlers/JavacHandlerUtil.java
index 5cbe08da..b4f2acc4 100644
--- a/src/core/lombok/javac/handlers/JavacHandlerUtil.java
+++ b/src/core/lombok/javac/handlers/JavacHandlerUtil.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009-2020 The Project Lombok Authors.
+ * Copyright (C) 2009-2021 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
@@ -807,7 +807,7 @@ public class JavacHandlerUtil {
node = upToTypeNode(node);
if (node != null && node.get() instanceof JCClassDecl) {
- for (JCTree def : ((JCClassDecl)node.get()).defs) {
+ for (JCTree def : ((JCClassDecl) node.get()).defs) {
if (def instanceof JCMethodDecl) {
JCMethodDecl md = (JCMethodDecl) def;
if (md.name.contentEquals("<init>")) {
@@ -822,6 +822,30 @@ public class JavacHandlerUtil {
return MemberExistsResult.NOT_EXISTS;
}
+ /**
+ * Checks if there is at least one constructor that is generated by lombok.
+ *
+ * @param node Any node that represents the Type (TypeDeclaration) to look in, or any child node thereof.
+ */
+ public static boolean lombokConstructorExists(JavacNode node) {
+ node = upToTypeNode(node);
+
+ if (node != null && node.get() instanceof JCClassDecl) {
+ for (JCTree def : ((JCClassDecl) node.get()).defs) {
+ if (def instanceof JCMethodDecl) {
+ JCMethodDecl md = (JCMethodDecl) def;
+ if (md.name.contentEquals("<init>")) {
+ if ((md.mods.flags & Flags.GENERATEDCONSTR) != 0) continue;
+ if (isTolerate(node, md)) continue;
+ if (getGeneratedBy(def) != null) return true;
+ }
+ }
+ }
+ }
+
+ return false;
+ }
+
public static boolean isConstructorCall(final JCStatement statement) {
if (!(statement instanceof JCExpressionStatement)) return false;
JCExpression expr = ((JCExpressionStatement) statement).expr;
@@ -1924,17 +1948,30 @@ public class JavacHandlerUtil {
return out.toList();
}
- static boolean isClass(JavacNode typeNode) {
- return isClassAndDoesNotHaveFlags(typeNode, Flags.INTERFACE | Flags.ENUM | Flags.ANNOTATION);
+ /**
+ * Returns {@code true} if the provided node is an actual class and not some other type declaration (so, not an annotation definition, interface, enum, or record).
+ */
+ public static boolean isClass(JavacNode typeNode) {
+ return isClassAndDoesNotHaveFlags(typeNode, Flags.INTERFACE | Flags.ENUM | Flags.ANNOTATION | RECORD);
+ }
+
+ /**
+ * Returns {@code true} if the provided node is an actual class or enum and not some other type declaration (so, not an annotation definition, interface, or record).
+ */
+ public static boolean isClassOrEnum(JavacNode typeNode) {
+ return isClassAndDoesNotHaveFlags(typeNode, Flags.INTERFACE | Flags.ANNOTATION | RECORD);
}
- static boolean isClassOrEnum(JavacNode typeNode) {
- return isClassAndDoesNotHaveFlags(typeNode, Flags.INTERFACE | Flags.ANNOTATION);
+ /**
+ * Returns {@code true} if the provided node is a record declaration (so, not an annotation definition, interface, enum, or plain class).
+ */
+ public static boolean isRecord(JavacNode typeNode) {
+ return typeNode.getKind() == Kind.TYPE && (((JCClassDecl) typeNode.get()).mods.flags & RECORD) != 0;
}
- public static boolean isClassAndDoesNotHaveFlags(JavacNode typeNode, int flags) {
+ public static boolean isClassAndDoesNotHaveFlags(JavacNode typeNode, long flags) {
JCClassDecl typeDecl = null;
- if (typeNode.get() instanceof JCClassDecl) typeDecl = (JCClassDecl)typeNode.get();
+ if (typeNode.get() instanceof JCClassDecl) typeDecl = (JCClassDecl) typeNode.get();
else return false;
long typeDeclflags = typeDecl == null ? 0 : typeDecl.mods.flags;