mirror of
https://github.com/tiennm99/lombok.git
synced 2026-10-15 20:15:59 +00:00
Added confkey to make @NonNull generate a different exception because of the IllegalArgumentException vs. NullPointerException that we really don’t want to get into.
This commit is contained in:
1 parent
57c92478a9
commit
4b878f9ba9
25 files changed
+252
-94
No files matched your search
@@ -2,6 +2,7 @@ Lombok Changelog
|
||||
----------------
|
||||
|
||||
### v1.12.7 "Edgy Guinea Pig"
|
||||
* FEATURE: You can now configure aspects of lombok project wide (or even workspace wide, or just for a single package) via the [configuration system](http://projectlombok.org/features/configuration.html). You can configure many things; run `java -jar lombok.jar config -gv` for the complete list.
|
||||
* DEPRECATION: `@Delegate` has been moved to `lombok.experimental.Delegate`, and corner cases such as recursive delegation (delegating a type that itself has fields or methods annotated with `@Delegate`) are now error conditions. See the [feature documentation](http://projectlombok.org/features/experimental/Delegate.html) for more information.
|
||||
* FEATURE: It is now possible to put annotations, such as `@Nullable`, on the one parameter of generated `equals()` methods by specifying the `onParam=` option on `@EqualsAndHashCode`, similar to how that feature already exists for `@Setter`. [Issue #674](https://code.google.com/p/projectlombok/issues/detail?id=674)
|
||||
* CHANGE: suppressConstructorProperties should now be configured via lombok configuration. [Issue #659](https://code.google.com/p/projectlombok/issues/detail?id=659)
|
||||
|
||||
@@ -180,6 +180,13 @@ public class ConfigurationKeys {
|
||||
|
||||
// ----- NonNull -----
|
||||
|
||||
/**
|
||||
* lombok configuration: {@code lombok.nonNull.exceptionType} = <String: <em>a java exception type, such as {@code java.lang.IllegalArgumentException}</em>> (default: {@code java.lang.NullPointerException}).
|
||||
*
|
||||
* Sets the exception to throw if {@code @NonNull} is applied to a method parameter, and a caller passes in {@code null}.
|
||||
*/
|
||||
public static final ConfigurationKey<String> NON_NULL_EXCEPTION_TYPE = new ConfigurationKey<String>("lombok.nonNull.exceptionType", "The type of the exception to throw if a passed-in argument is null.") {};
|
||||
|
||||
/**
|
||||
* lombok configuration: {@code lombok.nonNull.flagUsage} = {@code WARNING} | {@code ERROR}.
|
||||
*
|
||||
@@ -269,7 +276,7 @@ public class ConfigurationKeys {
|
||||
public static final ConfigurationKey<FlagUsageType> LOG_XSLF4J_FLAG_USAGE = new ConfigurationKey<FlagUsageType>("lombok.log.xslf4j.flagUsage", "Emit a warning or error if @XSlf4j is used.") {};
|
||||
|
||||
/**
|
||||
* lombok configuration: {@code lombok.log.fieldName} = "aJavaIdentifier".
|
||||
* lombok configuration: {@code lombok.log.fieldName} = <String: aJavaIdentifier> (Default: {@code log}).
|
||||
*
|
||||
* If set the various log annotations (which make a log field) will use the stated identifier instead of {@code log} as a name.
|
||||
*/
|
||||
|
||||
@@ -68,6 +68,30 @@ public class HandlerUtil {
|
||||
return 97;
|
||||
}
|
||||
|
||||
/** Checks if the input is a valid class reference (not a primitive and does not have generics). */
|
||||
public static boolean isLegalBasicClassReference(String in) {
|
||||
boolean atStartOfIdentifier = true;
|
||||
|
||||
for (int i = 0; i < in.length(); i++) {
|
||||
char c = in.charAt(i);
|
||||
|
||||
if (atStartOfIdentifier) {
|
||||
if (!Character.isJavaIdentifierStart(c)) return false;
|
||||
atStartOfIdentifier = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (c == '.') {
|
||||
atStartOfIdentifier = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!Character.isJavaIdentifierPart(c)) return false;
|
||||
}
|
||||
|
||||
return !atStartOfIdentifier;
|
||||
}
|
||||
|
||||
/** Checks if the given name is a valid identifier.
|
||||
*
|
||||
* If it is, this returns {@code true} and does nothing else.
|
||||
@@ -204,6 +228,8 @@ public class HandlerUtil {
|
||||
/** Matches the simple part of any annotation that lombok considers as indicative of Nullable status. */
|
||||
public static final Pattern NULLABLE_PATTERN = Pattern.compile("^(?:nullable|checkfornull)$", Pattern.CASE_INSENSITIVE);
|
||||
|
||||
public static final String DEFAULT_EXCEPTION_FOR_NON_NULL = "java.lang.NullPointerException";
|
||||
|
||||
/**
|
||||
* Generates a getter name from a given field name.
|
||||
*
|
||||
|
||||
@@ -1396,17 +1396,35 @@ public class EclipseHandlerUtil {
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a new statement that checks if the given variable is null, and if so, throws a {@code NullPointerException} with the
|
||||
* Generates a new statement that checks if the given variable is null, and if so, throws a specified exception with the
|
||||
* variable name as message.
|
||||
*
|
||||
* @param exName The name of the exception to throw; normally {@code java.lang.NullPointerException}.
|
||||
*/
|
||||
public static Statement generateNullCheck(AbstractVariableDeclaration variable, ASTNode source) {
|
||||
public static Statement generateNullCheck(AbstractVariableDeclaration variable, EclipseNode sourceNode) {
|
||||
String exceptionType = sourceNode.getAst().readConfiguration(ConfigurationKeys.NON_NULL_EXCEPTION_TYPE);
|
||||
if (exceptionType == null) {
|
||||
exceptionType = HandlerUtil.DEFAULT_EXCEPTION_FOR_NON_NULL;
|
||||
} else {
|
||||
if (!HandlerUtil.isLegalBasicClassReference(exceptionType)) {
|
||||
sourceNode.addWarning("Configuration key contains invalid java type reference '" + exceptionType + "'; use something like 'java.lang.NullPointerException' as value for this key.");
|
||||
exceptionType = HandlerUtil.DEFAULT_EXCEPTION_FOR_NON_NULL;
|
||||
}
|
||||
}
|
||||
|
||||
ASTNode source = sourceNode.get();
|
||||
|
||||
int pS = source.sourceStart, pE = source.sourceEnd;
|
||||
long p = (long)pS << 32 | pE;
|
||||
|
||||
if (isPrimitive(variable.type)) return null;
|
||||
AllocationExpression exception = new AllocationExpression();
|
||||
setGeneratedBy(exception, source);
|
||||
exception.type = new QualifiedTypeReference(fromQualifiedName("java.lang.NullPointerException"), new long[]{p, p, p});
|
||||
int partCount = 0;
|
||||
for (int i = 0; i < exceptionType.length(); i++) if (exceptionType.charAt(i) == '.') partCount++;
|
||||
long[] ps = new long[partCount];
|
||||
Arrays.fill(ps, 0L);
|
||||
exception.type = new QualifiedTypeReference(fromQualifiedName(exceptionType), ps);
|
||||
setGeneratedBy(exception.type, source);
|
||||
exception.arguments = new Expression[] { new StringLiteral(variable.name, pS, pE, 0)};
|
||||
setGeneratedBy(exception.arguments[0], source);
|
||||
|
||||
@@ -120,7 +120,8 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
|
||||
fields.add(fieldNode);
|
||||
}
|
||||
|
||||
new HandleConstructor().generateConstructor(tdParent, AccessLevel.PACKAGE, fields, null, SkipIfConstructorExists.I_AM_BUILDER, null, Collections.<Annotation>emptyList(), ast);
|
||||
new HandleConstructor().generateConstructor(tdParent, AccessLevel.PACKAGE, fields, null, SkipIfConstructorExists.I_AM_BUILDER, null,
|
||||
Collections.<Annotation>emptyList(), annotationNode);
|
||||
|
||||
returnType = namePlusTypeParamsToTypeReference(td.name, td.typeParameters, p);
|
||||
typeParams = td.typeParameters;
|
||||
@@ -204,12 +205,14 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
|
||||
List<EclipseNode> fieldNodes = addFieldsToBuilder(builderType, namesOfParameters, typesOfParameters, ast);
|
||||
List<AbstractMethodDeclaration> newMethods = new ArrayList<AbstractMethodDeclaration>();
|
||||
for (EclipseNode fieldNode : fieldNodes) {
|
||||
MethodDeclaration newMethod = makeSetterMethodForBuilder(builderType, fieldNode, ast, builderInstance.fluent(), builderInstance.chain());
|
||||
MethodDeclaration newMethod = makeSetterMethodForBuilder(builderType, fieldNode, annotationNode, builderInstance.fluent(), builderInstance.chain());
|
||||
if (newMethod != null) newMethods.add(newMethod);
|
||||
}
|
||||
|
||||
if (constructorExists(builderType) == MemberExistsResult.NOT_EXISTS) {
|
||||
ConstructorDeclaration cd = HandleConstructor.createConstructor(AccessLevel.PACKAGE, builderType, Collections.<EclipseNode>emptyList(), null, ast, Collections.<Annotation>emptyList());
|
||||
ConstructorDeclaration cd = HandleConstructor.createConstructor(
|
||||
AccessLevel.PACKAGE, builderType, Collections.<EclipseNode>emptyList(), null,
|
||||
annotationNode, Collections.<Annotation>emptyList());
|
||||
if (cd != null) injectMethod(builderType, cd);
|
||||
}
|
||||
|
||||
@@ -334,7 +337,7 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
|
||||
|
||||
private static final AbstractMethodDeclaration[] EMPTY = {};
|
||||
|
||||
public MethodDeclaration makeSetterMethodForBuilder(EclipseNode builderType, EclipseNode fieldNode, ASTNode source, boolean fluent, boolean chain) {
|
||||
public MethodDeclaration makeSetterMethodForBuilder(EclipseNode builderType, EclipseNode fieldNode, EclipseNode sourceNode, boolean fluent, boolean chain) {
|
||||
TypeDeclaration td = (TypeDeclaration) builderType.get();
|
||||
AbstractMethodDeclaration[] existing = td.methods;
|
||||
if (existing == null) existing = EMPTY;
|
||||
@@ -352,7 +355,7 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
|
||||
String setterName = fluent ? fieldNode.getName() : toSetterName(builderType.getAst(), null, fieldNode.getName(), isBoolean);
|
||||
|
||||
return HandleSetter.createSetter(td, fieldNode, setterName, chain, ClassFileConstants.AccPublic,
|
||||
source, Collections.<Annotation>emptyList(), Collections.<Annotation>emptyList());
|
||||
sourceNode, Collections.<Annotation>emptyList(), Collections.<Annotation>emptyList());
|
||||
}
|
||||
|
||||
public EclipseNode findInnerClass(EclipseNode parent, String name) {
|
||||
|
||||
@@ -82,7 +82,7 @@ public class HandleConstructor {
|
||||
|
||||
List<Annotation> onConstructor = unboxAndRemoveAnnotationParameter(ast, "onConstructor", "@NoArgsConstructor(onConstructor=", annotationNode);
|
||||
|
||||
new HandleConstructor().generateConstructor(typeNode, level, fields, staticName, SkipIfConstructorExists.NO, null, onConstructor, ast);
|
||||
new HandleConstructor().generateConstructor(typeNode, level, fields, staticName, SkipIfConstructorExists.NO, null, onConstructor, annotationNode);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -106,7 +106,9 @@ public class HandleConstructor {
|
||||
|
||||
List<Annotation> onConstructor = unboxAndRemoveAnnotationParameter(ast, "onConstructor", "@RequiredArgsConstructor(onConstructor=", annotationNode);
|
||||
|
||||
new HandleConstructor().generateConstructor(typeNode, level, findRequiredFields(typeNode), staticName, SkipIfConstructorExists.NO, suppressConstructorProperties, onConstructor, ast);
|
||||
new HandleConstructor().generateConstructor(
|
||||
typeNode, level, findRequiredFields(typeNode), staticName, SkipIfConstructorExists.NO,
|
||||
suppressConstructorProperties, onConstructor, annotationNode);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -158,7 +160,9 @@ public class HandleConstructor {
|
||||
|
||||
List<Annotation> onConstructor = unboxAndRemoveAnnotationParameter(ast, "onConstructor", "@AllArgsConstructor(onConstructor=", annotationNode);
|
||||
|
||||
new HandleConstructor().generateConstructor(typeNode, level, findAllFields(typeNode), staticName, SkipIfConstructorExists.NO, suppressConstructorProperties, onConstructor, ast);
|
||||
new HandleConstructor().generateConstructor(
|
||||
typeNode, level, findAllFields(typeNode), staticName, SkipIfConstructorExists.NO,
|
||||
suppressConstructorProperties, onConstructor, annotationNode);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -176,19 +180,29 @@ public class HandleConstructor {
|
||||
return true;
|
||||
}
|
||||
|
||||
public void generateRequiredArgsConstructor(EclipseNode typeNode, AccessLevel level, String staticName, SkipIfConstructorExists skipIfConstructorExists, List<Annotation> onConstructor, ASTNode source) {
|
||||
generateConstructor(typeNode, level, findRequiredFields(typeNode), staticName, skipIfConstructorExists, null, onConstructor, source);
|
||||
public void generateRequiredArgsConstructor(
|
||||
EclipseNode typeNode, AccessLevel level, String staticName, SkipIfConstructorExists skipIfConstructorExists,
|
||||
List<Annotation> onConstructor, EclipseNode sourceNode) {
|
||||
|
||||
generateConstructor(typeNode, level, findRequiredFields(typeNode), staticName, skipIfConstructorExists, null, onConstructor, sourceNode);
|
||||
}
|
||||
|
||||
public void generateAllArgsConstructor(EclipseNode typeNode, AccessLevel level, String staticName, SkipIfConstructorExists skipIfConstructorExists, List<Annotation> onConstructor, ASTNode source) {
|
||||
generateConstructor(typeNode, level, findAllFields(typeNode), staticName, skipIfConstructorExists, null, onConstructor, source);
|
||||
public void generateAllArgsConstructor(
|
||||
EclipseNode typeNode, AccessLevel level, String staticName, SkipIfConstructorExists skipIfConstructorExists,
|
||||
List<Annotation> onConstructor, EclipseNode sourceNode) {
|
||||
|
||||
generateConstructor(typeNode, level, findAllFields(typeNode), staticName, skipIfConstructorExists, null, onConstructor, sourceNode);
|
||||
}
|
||||
|
||||
public enum SkipIfConstructorExists {
|
||||
YES, NO, I_AM_BUILDER;
|
||||
}
|
||||
|
||||
public void generateConstructor(EclipseNode typeNode, AccessLevel level, List<EclipseNode> fields, String staticName, SkipIfConstructorExists skipIfConstructorExists, Boolean suppressConstructorProperties, List<Annotation> onConstructor, ASTNode source) {
|
||||
public void generateConstructor(
|
||||
EclipseNode typeNode, AccessLevel level, List<EclipseNode> fields, String staticName, SkipIfConstructorExists skipIfConstructorExists,
|
||||
Boolean suppressConstructorProperties, List<Annotation> onConstructor, EclipseNode sourceNode) {
|
||||
|
||||
ASTNode source = sourceNode.get();
|
||||
boolean staticConstrRequired = staticName != null && !staticName.equals("");
|
||||
|
||||
if (skipIfConstructorExists != SkipIfConstructorExists.NO && constructorExists(typeNode) != MemberExistsResult.NOT_EXISTS) return;
|
||||
@@ -209,7 +223,9 @@ public class HandleConstructor {
|
||||
// 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);
|
||||
typeNode.addWarning(
|
||||
"Ignoring static constructor name: explicit @XxxArgsConstructor annotation present; its `staticName` parameter will be used.",
|
||||
source.sourceStart, source.sourceEnd);
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -217,7 +233,9 @@ public class HandleConstructor {
|
||||
}
|
||||
}
|
||||
|
||||
ConstructorDeclaration constr = createConstructor(staticConstrRequired ? AccessLevel.PRIVATE : level, typeNode, fields, suppressConstructorProperties, source, onConstructor);
|
||||
ConstructorDeclaration constr = createConstructor(
|
||||
staticConstrRequired ? AccessLevel.PRIVATE : level, typeNode, fields,
|
||||
suppressConstructorProperties, sourceNode, onConstructor);
|
||||
injectMethod(typeNode, constr);
|
||||
if (staticConstrRequired) {
|
||||
MethodDeclaration staticConstr = createStaticConstructor(level, staticName, typeNode, fields, source);
|
||||
@@ -259,8 +277,9 @@ public class HandleConstructor {
|
||||
|
||||
public static ConstructorDeclaration createConstructor(
|
||||
AccessLevel level, EclipseNode type, Collection<EclipseNode> fields,
|
||||
Boolean suppressConstructorProperties, ASTNode source, List<Annotation> onConstructor) {
|
||||
Boolean suppressConstructorProperties, EclipseNode sourceNode, List<Annotation> onConstructor) {
|
||||
|
||||
ASTNode source = sourceNode.get();
|
||||
TypeDeclaration typeDeclaration = ((TypeDeclaration)type.get());
|
||||
long p = (long)source.sourceStart << 32 | source.sourceEnd;
|
||||
|
||||
@@ -311,7 +330,7 @@ public class HandleConstructor {
|
||||
Annotation[] nonNulls = findAnnotations(field, NON_NULL_PATTERN);
|
||||
Annotation[] nullables = findAnnotations(field, NULLABLE_PATTERN);
|
||||
if (nonNulls.length != 0) {
|
||||
Statement nullCheck = generateNullCheck(field, source);
|
||||
Statement nullCheck = generateNullCheck(field, sourceNode);
|
||||
if (nullCheck != null) nullChecks.add(nullCheck);
|
||||
}
|
||||
Annotation[] copiedAnnotations = copyAnnotations(source, nonNulls, nullables);
|
||||
|
||||
@@ -70,6 +70,8 @@ public class HandleData extends EclipseAnnotationHandler<Data> {
|
||||
new HandleSetter().generateSetterForType(typeNode, annotationNode, AccessLevel.PUBLIC, true);
|
||||
new HandleEqualsAndHashCode().generateEqualsAndHashCodeForType(typeNode, annotationNode);
|
||||
new HandleToString().generateToStringForType(typeNode, annotationNode);
|
||||
new HandleConstructor().generateRequiredArgsConstructor(typeNode, AccessLevel.PUBLIC, ann.staticConstructor(), SkipIfConstructorExists.YES, Collections.<Annotation>emptyList(), ast);
|
||||
new HandleConstructor().generateRequiredArgsConstructor(
|
||||
typeNode, AccessLevel.PUBLIC, ann.staticConstructor(), SkipIfConstructorExists.YES,
|
||||
Collections.<Annotation>emptyList(), annotationNode);
|
||||
}
|
||||
}
|
||||
@@ -99,7 +99,7 @@ public class HandleNonNull extends EclipseAnnotationHandler<NonNull> {
|
||||
// and if they exist, create a new method in the class: 'private static <T> T lombok$nullCheck(T expr, String msg) {if (expr == null) throw NPE; return expr;}' and
|
||||
// wrap all references to it in the super/this to a call to this method.
|
||||
|
||||
Statement nullCheck = generateNullCheck(arg, ast);
|
||||
Statement nullCheck = generateNullCheck(arg, annotationNode);
|
||||
|
||||
if (nullCheck == null) {
|
||||
// @NonNull applied to a primitive. Kinda pointless. Let's generate a warning.
|
||||
|
||||
@@ -90,7 +90,7 @@ public class HandleSetter extends EclipseAnnotationHandler<Setter> {
|
||||
//Skip final fields.
|
||||
if ((fieldDecl.modifiers & ClassFileConstants.AccFinal) != 0) continue;
|
||||
|
||||
generateSetterForField(field, pos.get(), level);
|
||||
generateSetterForField(field, pos, level);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -107,7 +107,7 @@ public class HandleSetter extends EclipseAnnotationHandler<Setter> {
|
||||
* If not, the setter is still generated if it isn't already there, though there will not
|
||||
* be a warning if its already there. The default access level is used.
|
||||
*/
|
||||
public void generateSetterForField(EclipseNode fieldNode, ASTNode pos, AccessLevel level) {
|
||||
public void generateSetterForField(EclipseNode fieldNode, EclipseNode sourceNode, AccessLevel level) {
|
||||
if (hasAnnotation(Setter.class, fieldNode)) {
|
||||
//The annotation will make it happen, so we can skip it.
|
||||
return;
|
||||
@@ -115,7 +115,7 @@ public class HandleSetter extends EclipseAnnotationHandler<Setter> {
|
||||
|
||||
List<Annotation> empty = Collections.emptyList();
|
||||
|
||||
createSetterForField(level, fieldNode, fieldNode, pos, false, empty, empty);
|
||||
createSetterForField(level, fieldNode, sourceNode, false, empty, empty);
|
||||
}
|
||||
|
||||
public void handle(AnnotationValues<Setter> annotation, Annotation ast, EclipseNode annotationNode) {
|
||||
@@ -130,7 +130,7 @@ public class HandleSetter extends EclipseAnnotationHandler<Setter> {
|
||||
|
||||
switch (node.getKind()) {
|
||||
case FIELD:
|
||||
createSetterForFields(level, annotationNode.upFromAnnotationToFields(), annotationNode, annotationNode.get(), true, onMethod, onParam);
|
||||
createSetterForFields(level, annotationNode.upFromAnnotationToFields(), annotationNode, true, onMethod, onParam);
|
||||
break;
|
||||
case TYPE:
|
||||
if (!onMethod.isEmpty()) {
|
||||
@@ -144,19 +144,20 @@ public class HandleSetter extends EclipseAnnotationHandler<Setter> {
|
||||
}
|
||||
}
|
||||
|
||||
public void createSetterForFields(AccessLevel level, Collection<EclipseNode> fieldNodes, EclipseNode errorNode, ASTNode source, boolean whineIfExists, List<Annotation> onMethod, List<Annotation> onParam) {
|
||||
public void createSetterForFields(AccessLevel level, Collection<EclipseNode> fieldNodes, EclipseNode sourceNode, boolean whineIfExists, List<Annotation> onMethod, List<Annotation> onParam) {
|
||||
for (EclipseNode fieldNode : fieldNodes) {
|
||||
createSetterForField(level, fieldNode, errorNode, source, whineIfExists, onMethod, onParam);
|
||||
createSetterForField(level, fieldNode, sourceNode, whineIfExists, onMethod, onParam);
|
||||
}
|
||||
}
|
||||
|
||||
public void createSetterForField(
|
||||
AccessLevel level, EclipseNode fieldNode, EclipseNode errorNode,
|
||||
ASTNode source, boolean whineIfExists, List<Annotation> onMethod,
|
||||
AccessLevel level, EclipseNode fieldNode, EclipseNode sourceNode,
|
||||
boolean whineIfExists, List<Annotation> onMethod,
|
||||
List<Annotation> onParam) {
|
||||
|
||||
ASTNode source = sourceNode.get();
|
||||
if (fieldNode.getKind() != Kind.FIELD) {
|
||||
errorNode.addError("@Setter is only supported on a class or a field.");
|
||||
sourceNode.addError("@Setter is only supported on a class or a field.");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -167,7 +168,7 @@ public class HandleSetter extends EclipseAnnotationHandler<Setter> {
|
||||
boolean shouldReturnThis = shouldReturnThis(fieldNode);
|
||||
|
||||
if (setterName == null) {
|
||||
errorNode.addWarning("Not generating setter for this field: It does not fit your @Accessors prefix list.");
|
||||
fieldNode.addWarning("Not generating setter for this field: It does not fit your @Accessors prefix list.");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -181,7 +182,7 @@ public class HandleSetter extends EclipseAnnotationHandler<Setter> {
|
||||
if (whineIfExists) {
|
||||
String altNameExpl = "";
|
||||
if (!altName.equals(setterName)) altNameExpl = String.format(" (%s)", altName);
|
||||
errorNode.addWarning(
|
||||
fieldNode.addWarning(
|
||||
String.format("Not generating %s(): A method with that name already exists%s", setterName, altNameExpl));
|
||||
}
|
||||
return;
|
||||
@@ -191,12 +192,13 @@ public class HandleSetter extends EclipseAnnotationHandler<Setter> {
|
||||
}
|
||||
}
|
||||
|
||||
MethodDeclaration method = createSetter((TypeDeclaration) fieldNode.up().get(), fieldNode, setterName, shouldReturnThis, modifier, source, onMethod, onParam);
|
||||
MethodDeclaration method = createSetter((TypeDeclaration) fieldNode.up().get(), fieldNode, setterName, shouldReturnThis, modifier, sourceNode, onMethod, onParam);
|
||||
injectMethod(fieldNode.up(), method);
|
||||
}
|
||||
|
||||
static MethodDeclaration createSetter(TypeDeclaration parent, EclipseNode fieldNode, String name, boolean shouldReturnThis, int modifier, ASTNode source, List<Annotation> onMethod, List<Annotation> onParam) {
|
||||
static MethodDeclaration createSetter(TypeDeclaration parent, EclipseNode fieldNode, String name, boolean shouldReturnThis, int modifier, EclipseNode sourceNode, List<Annotation> onMethod, List<Annotation> onParam) {
|
||||
FieldDeclaration field = (FieldDeclaration) fieldNode.get();
|
||||
ASTNode source = sourceNode.get();
|
||||
int pS = source.sourceStart, pE = source.sourceEnd;
|
||||
long p = (long)pS << 32 | pE;
|
||||
MethodDeclaration method = new MethodDeclaration(parent.compilationResult);
|
||||
@@ -239,7 +241,7 @@ public class HandleSetter extends EclipseAnnotationHandler<Setter> {
|
||||
if (nonNulls.length == 0) {
|
||||
statements.add(assignment);
|
||||
} else {
|
||||
Statement nullCheck = generateNullCheck(field, source);
|
||||
Statement nullCheck = generateNullCheck(field, sourceNode);
|
||||
if (nullCheck != null) statements.add(nullCheck);
|
||||
statements.add(assignment);
|
||||
}
|
||||
|
||||
@@ -83,6 +83,7 @@ public class HandleValue extends EclipseAnnotationHandler<Value> {
|
||||
new HandleGetter().generateGetterForType(typeNode, annotationNode, AccessLevel.PUBLIC, true);
|
||||
new HandleEqualsAndHashCode().generateEqualsAndHashCodeForType(typeNode, annotationNode);
|
||||
new HandleToString().generateToStringForType(typeNode, annotationNode);
|
||||
new HandleConstructor().generateAllArgsConstructor(typeNode, AccessLevel.PUBLIC, ann.staticConstructor(), SkipIfConstructorExists.YES, Collections.<Annotation>emptyList(), ast);
|
||||
new HandleConstructor().generateAllArgsConstructor(typeNode, AccessLevel.PUBLIC, ann.staticConstructor(), SkipIfConstructorExists.YES,
|
||||
Collections.<Annotation>emptyList(), annotationNode);
|
||||
}
|
||||
}
|
||||
@@ -88,7 +88,7 @@ public class HandleWither extends EclipseAnnotationHandler<Wither> {
|
||||
//Skip final fields.
|
||||
if ((fieldDecl.modifiers & ClassFileConstants.AccFinal) != 0 && fieldDecl.initialization != null) continue;
|
||||
|
||||
generateWitherForField(field, pos.get(), level);
|
||||
generateWitherForField(field, pos, level);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -106,7 +106,7 @@ public class HandleWither extends EclipseAnnotationHandler<Wither> {
|
||||
* If not, the wither is still generated if it isn't already there, though there will not
|
||||
* be a warning if its already there. The default access level is used.
|
||||
*/
|
||||
public void generateWitherForField(EclipseNode fieldNode, ASTNode pos, AccessLevel level) {
|
||||
public void generateWitherForField(EclipseNode fieldNode, EclipseNode sourceNode, AccessLevel level) {
|
||||
for (EclipseNode child : fieldNode.down()) {
|
||||
if (child.getKind() == Kind.ANNOTATION) {
|
||||
if (annotationTypeMatches(Wither.class, child)) {
|
||||
@@ -117,7 +117,7 @@ public class HandleWither extends EclipseAnnotationHandler<Wither> {
|
||||
}
|
||||
|
||||
List<Annotation> empty = Collections.emptyList();
|
||||
createWitherForField(level, fieldNode, fieldNode, pos, false, empty, empty);
|
||||
createWitherForField(level, fieldNode, sourceNode, false, empty, empty);
|
||||
}
|
||||
|
||||
@Override public void handle(AnnotationValues<Wither> annotation, Annotation ast, EclipseNode annotationNode) {
|
||||
@@ -132,7 +132,7 @@ public class HandleWither extends EclipseAnnotationHandler<Wither> {
|
||||
|
||||
switch (node.getKind()) {
|
||||
case FIELD:
|
||||
createWitherForFields(level, annotationNode.upFromAnnotationToFields(), annotationNode, annotationNode.get(), true, onMethod, onParam);
|
||||
createWitherForFields(level, annotationNode.upFromAnnotationToFields(), annotationNode, true, onMethod, onParam);
|
||||
break;
|
||||
case TYPE:
|
||||
if (!onMethod.isEmpty()) {
|
||||
@@ -146,18 +146,20 @@ public class HandleWither extends EclipseAnnotationHandler<Wither> {
|
||||
}
|
||||
}
|
||||
|
||||
public void createWitherForFields(AccessLevel level, Collection<EclipseNode> fieldNodes, EclipseNode errorNode, ASTNode source, boolean whineIfExists, List<Annotation> onMethod, List<Annotation> onParam) {
|
||||
public void createWitherForFields(AccessLevel level, Collection<EclipseNode> fieldNodes, EclipseNode sourceNode, boolean whineIfExists, List<Annotation> onMethod, List<Annotation> onParam) {
|
||||
for (EclipseNode fieldNode : fieldNodes) {
|
||||
createWitherForField(level, fieldNode, errorNode, source, whineIfExists, onMethod, onParam);
|
||||
createWitherForField(level, fieldNode, sourceNode, whineIfExists, onMethod, onParam);
|
||||
}
|
||||
}
|
||||
|
||||
public void createWitherForField(
|
||||
AccessLevel level, EclipseNode fieldNode, EclipseNode errorNode,
|
||||
ASTNode source, boolean whineIfExists, List<Annotation> onMethod,
|
||||
AccessLevel level, EclipseNode fieldNode, EclipseNode sourceNode,
|
||||
boolean whineIfExists, List<Annotation> onMethod,
|
||||
List<Annotation> onParam) {
|
||||
|
||||
ASTNode source = sourceNode.get();
|
||||
if (fieldNode.getKind() != Kind.FIELD) {
|
||||
errorNode.addError("@Wither is only supported on a class or a field.");
|
||||
sourceNode.addError("@Wither is only supported on a class or a field.");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -167,22 +169,22 @@ public class HandleWither extends EclipseAnnotationHandler<Wither> {
|
||||
String witherName = toWitherName(fieldNode, isBoolean);
|
||||
|
||||
if (witherName == null) {
|
||||
errorNode.addWarning("Not generating wither for this field: It does not fit your @Accessors prefix list.");
|
||||
fieldNode.addWarning("Not generating wither for this field: It does not fit your @Accessors prefix list.");
|
||||
return;
|
||||
}
|
||||
|
||||
if ((field.modifiers & ClassFileConstants.AccStatic) != 0) {
|
||||
errorNode.addWarning("Not generating wither for this field: Withers cannot be generated for static fields.");
|
||||
fieldNode.addWarning("Not generating wither for this field: Withers cannot be generated for static fields.");
|
||||
return;
|
||||
}
|
||||
|
||||
if ((field.modifiers & ClassFileConstants.AccFinal) != 0 && field.initialization != null) {
|
||||
errorNode.addWarning("Not generating wither for this field: Withers cannot be generated for final, initialized fields.");
|
||||
fieldNode.addWarning("Not generating wither for this field: Withers cannot be generated for final, initialized fields.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (field.name != null && field.name.length > 0 && field.name[0] == '$') {
|
||||
errorNode.addWarning("Not generating wither for this field: Withers cannot be generated for fields starting with $.");
|
||||
fieldNode.addWarning("Not generating wither for this field: Withers cannot be generated for fields starting with $.");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -194,7 +196,7 @@ public class HandleWither extends EclipseAnnotationHandler<Wither> {
|
||||
if (whineIfExists) {
|
||||
String altNameExpl = "";
|
||||
if (!altName.equals(witherName)) altNameExpl = String.format(" (%s)", altName);
|
||||
errorNode.addWarning(
|
||||
fieldNode.addWarning(
|
||||
String.format("Not generating %s(): A method with that name already exists%s", witherName, altNameExpl));
|
||||
}
|
||||
return;
|
||||
@@ -206,11 +208,12 @@ public class HandleWither extends EclipseAnnotationHandler<Wither> {
|
||||
|
||||
int modifier = toEclipseModifier(level);
|
||||
|
||||
MethodDeclaration method = createWither((TypeDeclaration) fieldNode.up().get(), fieldNode, witherName, modifier, source, onMethod, onParam);
|
||||
MethodDeclaration method = createWither((TypeDeclaration) fieldNode.up().get(), fieldNode, witherName, modifier, sourceNode, onMethod, onParam);
|
||||
injectMethod(fieldNode.up(), method);
|
||||
}
|
||||
|
||||
public MethodDeclaration createWither(TypeDeclaration parent, EclipseNode fieldNode, String name, int modifier, ASTNode source, List<Annotation> onMethod, List<Annotation> onParam) {
|
||||
public MethodDeclaration createWither(TypeDeclaration parent, EclipseNode fieldNode, String name, int modifier, EclipseNode sourceNode, List<Annotation> onMethod, List<Annotation> onParam) {
|
||||
ASTNode source = sourceNode.get();
|
||||
if (name == null) return null;
|
||||
FieldDeclaration field = (FieldDeclaration) fieldNode.get();
|
||||
int pS = source.sourceStart, pE = source.sourceEnd;
|
||||
@@ -273,7 +276,7 @@ public class HandleWither extends EclipseAnnotationHandler<Wither> {
|
||||
Annotation[] nullables = findAnnotations(field, NULLABLE_PATTERN);
|
||||
List<Statement> statements = new ArrayList<Statement>(5);
|
||||
if (nonNulls.length > 0) {
|
||||
Statement nullCheck = generateNullCheck(field, source);
|
||||
Statement nullCheck = generateNullCheck(field, sourceNode);
|
||||
if (nullCheck != null) statements.add(nullCheck);
|
||||
}
|
||||
statements.add(returnStatement);
|
||||
|
||||
@@ -194,12 +194,12 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> {
|
||||
java.util.List<JavacNode> fieldNodes = addFieldsToBuilder(builderType, namesOfParameters, typesOfParameters, ast);
|
||||
java.util.List<JCMethodDecl> newMethods = new ArrayList<JCMethodDecl>();
|
||||
for (JavacNode fieldNode : fieldNodes) {
|
||||
JCMethodDecl newMethod = makeSetterMethodForBuilder(builderType, fieldNode, ast, builderInstance.fluent(), builderInstance.chain());
|
||||
JCMethodDecl newMethod = makeSetterMethodForBuilder(builderType, fieldNode, annotationNode, builderInstance.fluent(), builderInstance.chain());
|
||||
if (newMethod != null) newMethods.add(newMethod);
|
||||
}
|
||||
|
||||
if (constructorExists(builderType) == MemberExistsResult.NOT_EXISTS) {
|
||||
JCMethodDecl cd = HandleConstructor.createConstructor(AccessLevel.PACKAGE, List.<JCAnnotation>nil(), builderType, List.<JavacNode>nil(), null, ast);
|
||||
JCMethodDecl cd = HandleConstructor.createConstructor(AccessLevel.PACKAGE, List.<JCAnnotation>nil(), builderType, List.<JavacNode>nil(), null, annotationNode);
|
||||
if (cd != null) injectMethod(builderType, cd);
|
||||
}
|
||||
|
||||
@@ -300,7 +300,7 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> {
|
||||
}
|
||||
|
||||
|
||||
public JCMethodDecl makeSetterMethodForBuilder(JavacNode builderType, JavacNode fieldNode, JCTree source, boolean fluent, boolean chain) {
|
||||
public JCMethodDecl makeSetterMethodForBuilder(JavacNode builderType, JavacNode fieldNode, JavacNode source, boolean fluent, boolean chain) {
|
||||
Name fieldName = ((JCVariableDecl) fieldNode.get()).name;
|
||||
|
||||
for (JavacNode child : builderType.down()) {
|
||||
|
||||
@@ -214,7 +214,7 @@ public class HandleConstructor {
|
||||
}
|
||||
}
|
||||
|
||||
JCMethodDecl constr = createConstructor(staticConstrRequired ? AccessLevel.PRIVATE : level, onConstructor, typeNode, fields, suppressConstructorProperties, source.get());
|
||||
JCMethodDecl constr = createConstructor(staticConstrRequired ? AccessLevel.PRIVATE : level, onConstructor, typeNode, fields, suppressConstructorProperties, source);
|
||||
injectMethod(typeNode, constr);
|
||||
if (staticConstrRequired) {
|
||||
JCMethodDecl staticConstr = createStaticConstructor(staticName, level, typeNode, fields, source.get());
|
||||
@@ -236,7 +236,7 @@ public class HandleConstructor {
|
||||
mods.annotations = mods.annotations.append(annotation);
|
||||
}
|
||||
|
||||
public static JCMethodDecl createConstructor(AccessLevel level, List<JCAnnotation> onConstructor, JavacNode typeNode, List<JavacNode> fields, Boolean suppressConstructorProperties, JCTree source) {
|
||||
public static JCMethodDecl createConstructor(AccessLevel level, List<JCAnnotation> onConstructor, JavacNode typeNode, List<JavacNode> fields, Boolean suppressConstructorProperties, JavacNode source) {
|
||||
JavacTreeMaker maker = typeNode.getTreeMaker();
|
||||
|
||||
boolean isEnum = (((JCClassDecl) typeNode.get()).mods.flags & Flags.ENUM) != 0;
|
||||
@@ -268,7 +268,7 @@ public class HandleConstructor {
|
||||
assigns.append(maker.Exec(assign));
|
||||
|
||||
if (!nonNulls.isEmpty()) {
|
||||
JCStatement nullCheck = generateNullCheck(maker, fieldNode);
|
||||
JCStatement nullCheck = generateNullCheck(maker, fieldNode, source);
|
||||
if (nullCheck != null) nullChecks.append(nullCheck);
|
||||
}
|
||||
}
|
||||
@@ -280,7 +280,8 @@ public class HandleConstructor {
|
||||
if (onConstructor != null) mods.annotations = mods.annotations.appendList(copyAnnotations(onConstructor));
|
||||
|
||||
return recursiveSetGeneratedBy(maker.MethodDef(mods, typeNode.toName("<init>"),
|
||||
null, List.<JCTypeParameter>nil(), params.toList(), List.<JCExpression>nil(), maker.Block(0L, nullChecks.appendList(assigns).toList()), null), source, typeNode.getContext());
|
||||
null, List.<JCTypeParameter>nil(), params.toList(), List.<JCExpression>nil(),
|
||||
maker.Block(0L, nullChecks.appendList(assigns).toList()), null), source.get(), typeNode.getContext());
|
||||
}
|
||||
|
||||
public static boolean isLocalType(JavacNode type) {
|
||||
|
||||
@@ -84,8 +84,6 @@ public class HandleNonNull extends JavacAnnotationHandler<NonNull> {
|
||||
return;
|
||||
}
|
||||
|
||||
// if (JavacHandlerUtil.isGenerated(declaration)) return;
|
||||
|
||||
if (declaration.body == null) {
|
||||
annotationNode.addWarning("@NonNull is meaningless on a parameter of an abstract method.");
|
||||
return;
|
||||
@@ -95,7 +93,7 @@ public class HandleNonNull extends JavacAnnotationHandler<NonNull> {
|
||||
// and if they exist, create a new method in the class: 'private static <T> T lombok$nullCheck(T expr, String msg) {if (expr == null) throw NPE; return expr;}' and
|
||||
// wrap all references to it in the super/this to a call to this method.
|
||||
|
||||
JCStatement nullCheck = recursiveSetGeneratedBy(generateNullCheck(annotationNode.getTreeMaker(), annotationNode.up()), ast, annotationNode.getContext());
|
||||
JCStatement nullCheck = recursiveSetGeneratedBy(generateNullCheck(annotationNode.getTreeMaker(), annotationNode.up(), annotationNode), ast, annotationNode.getContext());
|
||||
|
||||
if (nullCheck == null) {
|
||||
// @NonNull applied to a primitive. Kinda pointless. Let's generate a warning.
|
||||
|
||||
@@ -41,7 +41,6 @@ import lombok.javac.handlers.JavacHandlerUtil.FieldAccess;
|
||||
import org.mangosdk.spi.ProviderFor;
|
||||
|
||||
import com.sun.tools.javac.code.Flags;
|
||||
import com.sun.tools.javac.tree.JCTree;
|
||||
import com.sun.tools.javac.tree.JCTree.JCAnnotation;
|
||||
import com.sun.tools.javac.tree.JCTree.JCAssign;
|
||||
import com.sun.tools.javac.tree.JCTree.JCBlock;
|
||||
@@ -52,7 +51,6 @@ import com.sun.tools.javac.tree.JCTree.JCReturn;
|
||||
import com.sun.tools.javac.tree.JCTree.JCStatement;
|
||||
import com.sun.tools.javac.tree.JCTree.JCTypeParameter;
|
||||
import com.sun.tools.javac.tree.JCTree.JCVariableDecl;
|
||||
import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
|
||||
import com.sun.tools.javac.util.List;
|
||||
import com.sun.tools.javac.util.ListBuffer;
|
||||
import com.sun.tools.javac.util.Name;
|
||||
@@ -90,7 +88,7 @@ public class HandleSetter extends JavacAnnotationHandler<Setter> {
|
||||
//Skip final fields.
|
||||
if ((fieldDecl.mods.flags & Flags.FINAL) != 0) continue;
|
||||
|
||||
generateSetterForField(field, errorNode.get(), level);
|
||||
generateSetterForField(field, errorNode, level);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -109,13 +107,13 @@ public class HandleSetter extends JavacAnnotationHandler<Setter> {
|
||||
* @param fieldNode The node representing the field you want a setter for.
|
||||
* @param pos The node responsible for generating the setter (the {@code @Data} or {@code @Setter} annotation).
|
||||
*/
|
||||
public void generateSetterForField(JavacNode fieldNode, DiagnosticPosition pos, AccessLevel level) {
|
||||
public void generateSetterForField(JavacNode fieldNode, JavacNode sourceNode, AccessLevel level) {
|
||||
if (hasAnnotation(Setter.class, fieldNode)) {
|
||||
//The annotation will make it happen, so we can skip it.
|
||||
return;
|
||||
}
|
||||
|
||||
createSetterForField(level, fieldNode, fieldNode, false, List.<JCAnnotation>nil(), List.<JCAnnotation>nil());
|
||||
createSetterForField(level, fieldNode, sourceNode, false, List.<JCAnnotation>nil(), List.<JCAnnotation>nil());
|
||||
}
|
||||
|
||||
@Override public void handle(AnnotationValues<Setter> annotation, JCAnnotation ast, JavacNode annotationNode) {
|
||||
@@ -150,7 +148,7 @@ public class HandleSetter extends JavacAnnotationHandler<Setter> {
|
||||
}
|
||||
}
|
||||
|
||||
public void createSetterForField(AccessLevel level, JavacNode fieldNode, JavacNode source, boolean whineIfExists, List<JCAnnotation> onMethod, List<JCAnnotation> onParam) {
|
||||
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.");
|
||||
return;
|
||||
@@ -160,12 +158,12 @@ public class HandleSetter extends JavacAnnotationHandler<Setter> {
|
||||
String methodName = toSetterName(fieldNode);
|
||||
|
||||
if (methodName == null) {
|
||||
source.addWarning("Not generating setter for this field: It does not fit your @Accessors prefix list.");
|
||||
fieldNode.addWarning("Not generating setter for this field: It does not fit your @Accessors prefix list.");
|
||||
return;
|
||||
}
|
||||
|
||||
if ((fieldDecl.mods.flags & Flags.FINAL) != 0) {
|
||||
source.addWarning("Not generating setter for this field: Setters cannot be generated for final fields.");
|
||||
fieldNode.addWarning("Not generating setter for this field: Setters cannot be generated for final fields.");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -177,7 +175,7 @@ public class HandleSetter extends JavacAnnotationHandler<Setter> {
|
||||
if (whineIfExists) {
|
||||
String altNameExpl = "";
|
||||
if (!altName.equals(methodName)) altNameExpl = String.format(" (%s)", altName);
|
||||
source.addWarning(
|
||||
fieldNode.addWarning(
|
||||
String.format("Not generating %s(): A method with that name already exists%s", methodName, altNameExpl));
|
||||
}
|
||||
return;
|
||||
@@ -189,17 +187,17 @@ public class HandleSetter extends JavacAnnotationHandler<Setter> {
|
||||
|
||||
long access = toJavacModifier(level) | (fieldDecl.mods.flags & Flags.STATIC);
|
||||
|
||||
JCMethodDecl createdSetter = createSetter(access, fieldNode, fieldNode.getTreeMaker(), source.get(), onMethod, onParam);
|
||||
JCMethodDecl createdSetter = createSetter(access, fieldNode, fieldNode.getTreeMaker(), sourceNode, onMethod, onParam);
|
||||
injectMethod(fieldNode.up(), createdSetter);
|
||||
}
|
||||
|
||||
public static JCMethodDecl createSetter(long access, JavacNode field, JavacTreeMaker treeMaker, JCTree source, List<JCAnnotation> onMethod, List<JCAnnotation> onParam) {
|
||||
public static JCMethodDecl createSetter(long access, JavacNode field, JavacTreeMaker treeMaker, JavacNode source, List<JCAnnotation> onMethod, List<JCAnnotation> onParam) {
|
||||
String setterName = toSetterName(field);
|
||||
boolean returnThis = shouldReturnThis(field);
|
||||
return createSetter(access, field, treeMaker, setterName, returnThis, source, onMethod, onParam);
|
||||
}
|
||||
|
||||
public static JCMethodDecl createSetter(long access, JavacNode field, JavacTreeMaker treeMaker, String setterName, boolean shouldReturnThis, JCTree source, List<JCAnnotation> onMethod, List<JCAnnotation> onParam) {
|
||||
public static JCMethodDecl createSetter(long access, JavacNode field, JavacTreeMaker treeMaker, String setterName, boolean shouldReturnThis, JavacNode source, List<JCAnnotation> onMethod, List<JCAnnotation> onParam) {
|
||||
if (setterName == null) return null;
|
||||
|
||||
JCVariableDecl fieldDecl = (JCVariableDecl) field.get();
|
||||
@@ -220,7 +218,7 @@ public class HandleSetter extends JavacAnnotationHandler<Setter> {
|
||||
if (nonNulls.isEmpty()) {
|
||||
statements.append(treeMaker.Exec(assign));
|
||||
} else {
|
||||
JCStatement nullCheck = generateNullCheck(treeMaker, field);
|
||||
JCStatement nullCheck = generateNullCheck(treeMaker, field, source);
|
||||
if (nullCheck != null) statements.append(nullCheck);
|
||||
statements.append(treeMaker.Exec(assign));
|
||||
}
|
||||
@@ -253,7 +251,7 @@ public class HandleSetter extends JavacAnnotationHandler<Setter> {
|
||||
}
|
||||
|
||||
JCMethodDecl decl = recursiveSetGeneratedBy(treeMaker.MethodDef(treeMaker.Modifiers(access, annsOnMethod), methodName, methodType,
|
||||
methodGenericParams, parameters, throwsClauses, methodBody, annotationMethodDefaultValue), source, field.getContext());
|
||||
methodGenericParams, parameters, throwsClauses, methodBody, annotationMethodDefaultValue), source.get(), field.getContext());
|
||||
copyJavadoc(field, decl, CopyJavadoc.SETTER);
|
||||
return decl;
|
||||
}
|
||||
|
||||
@@ -41,7 +41,6 @@ import lombok.javac.handlers.JavacHandlerUtil.FieldAccess;
|
||||
import org.mangosdk.spi.ProviderFor;
|
||||
|
||||
import com.sun.tools.javac.code.Flags;
|
||||
import com.sun.tools.javac.tree.JCTree;
|
||||
import com.sun.tools.javac.tree.JCTree.JCAnnotation;
|
||||
import com.sun.tools.javac.tree.JCTree.JCBlock;
|
||||
import com.sun.tools.javac.tree.JCTree.JCClassDecl;
|
||||
@@ -161,22 +160,22 @@ public class HandleWither extends JavacAnnotationHandler<Wither> {
|
||||
String methodName = toWitherName(fieldNode);
|
||||
|
||||
if (methodName == null) {
|
||||
source.addWarning("Not generating wither for this field: It does not fit your @Accessors prefix list.");
|
||||
fieldNode.addWarning("Not generating wither for this field: It does not fit your @Accessors prefix list.");
|
||||
return;
|
||||
}
|
||||
|
||||
if ((fieldDecl.mods.flags & Flags.STATIC) != 0) {
|
||||
source.addWarning("Not generating wither for this field: Withers cannot be generated for static fields.");
|
||||
fieldNode.addWarning("Not generating wither for this field: Withers cannot be generated for static fields.");
|
||||
return;
|
||||
}
|
||||
|
||||
if ((fieldDecl.mods.flags & Flags.FINAL) != 0 && fieldDecl.init != null) {
|
||||
source.addWarning("Not generating wither for this field: Withers cannot be generated for final, initialized fields.");
|
||||
fieldNode.addWarning("Not generating wither for this field: Withers cannot be generated for final, initialized fields.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (fieldDecl.name.toString().startsWith("$")) {
|
||||
source.addWarning("Not generating wither for this field: Withers cannot be generated for fields starting with $.");
|
||||
fieldNode.addWarning("Not generating wither for this field: Withers cannot be generated for fields starting with $.");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -188,7 +187,7 @@ public class HandleWither extends JavacAnnotationHandler<Wither> {
|
||||
if (whineIfExists) {
|
||||
String altNameExpl = "";
|
||||
if (!altName.equals(methodName)) altNameExpl = String.format(" (%s)", altName);
|
||||
source.addWarning(
|
||||
fieldNode.addWarning(
|
||||
String.format("Not generating %s(): A method with that name already exists%s", methodName, altNameExpl));
|
||||
}
|
||||
return;
|
||||
@@ -200,11 +199,11 @@ public class HandleWither extends JavacAnnotationHandler<Wither> {
|
||||
|
||||
long access = toJavacModifier(level);
|
||||
|
||||
JCMethodDecl createdWither = createWither(access, fieldNode, fieldNode.getTreeMaker(), source.get(), onMethod, onParam);
|
||||
JCMethodDecl createdWither = createWither(access, fieldNode, fieldNode.getTreeMaker(), source, onMethod, onParam);
|
||||
injectMethod(fieldNode.up(), createdWither);
|
||||
}
|
||||
|
||||
public JCMethodDecl createWither(long access, JavacNode field, JavacTreeMaker maker, JCTree source, List<JCAnnotation> onMethod, List<JCAnnotation> onParam) {
|
||||
public JCMethodDecl createWither(long access, JavacNode field, JavacTreeMaker maker, JavacNode source, List<JCAnnotation> onMethod, List<JCAnnotation> onParam) {
|
||||
String witherName = toWitherName(field);
|
||||
if (witherName == null) return null;
|
||||
|
||||
@@ -249,7 +248,7 @@ public class HandleWither extends JavacAnnotationHandler<Wither> {
|
||||
if (nonNulls.isEmpty()) {
|
||||
statements.append(returnStatement);
|
||||
} else {
|
||||
JCStatement nullCheck = generateNullCheck(maker, field);
|
||||
JCStatement nullCheck = generateNullCheck(maker, field, source);
|
||||
if (nullCheck != null) statements.append(nullCheck);
|
||||
statements.append(returnStatement);
|
||||
}
|
||||
@@ -268,7 +267,7 @@ public class HandleWither extends JavacAnnotationHandler<Wither> {
|
||||
annsOnMethod = annsOnMethod.prepend(maker.Annotation(genJavaLangTypeRef(field, "Deprecated"), List.<JCExpression>nil()));
|
||||
}
|
||||
JCMethodDecl decl = recursiveSetGeneratedBy(maker.MethodDef(maker.Modifiers(access, annsOnMethod), methodName, returnType,
|
||||
methodGenericParams, parameters, throwsClauses, methodBody, annotationMethodDefaultValue), source, field.getContext());
|
||||
methodGenericParams, parameters, throwsClauses, methodBody, annotationMethodDefaultValue), source.get(), field.getContext());
|
||||
copyJavadoc(field, decl, CopyJavadoc.WITHER);
|
||||
return decl;
|
||||
}
|
||||
|
||||
@@ -898,6 +898,17 @@ public class JavacHandlerUtil {
|
||||
return flags;
|
||||
}
|
||||
|
||||
public static JCExpression genTypeRef(JavacNode node, String complexName) {
|
||||
String[] parts = complexName.split("\\.");
|
||||
if (parts.length > 2 && parts[0].equals("java") && parts[1].equals("lang")) {
|
||||
String[] subParts = new String[parts.length - 2];
|
||||
System.arraycopy(parts, 2, subParts, 0, subParts.length);
|
||||
return genJavaLangTypeRef(node, subParts);
|
||||
}
|
||||
|
||||
return chainDots(node, parts);
|
||||
}
|
||||
|
||||
public static JCExpression genJavaLangTypeRef(JavacNode node, String... simpleNames) {
|
||||
if (LombokOptionsFactory.getDelombokOptions(node.getContext()).getFormatPreferences().javaLangAsFqn()) {
|
||||
return chainDots(node, "java", "lang", simpleNames);
|
||||
@@ -1029,15 +1040,27 @@ public class JavacHandlerUtil {
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a new statement that checks if the given variable is null, and if so, throws a {@code NullPointerException} with the
|
||||
* Generates a new statement that checks if the given variable is null, and if so, throws a specified exception with the
|
||||
* variable name as message.
|
||||
*
|
||||
* @param exName The name of the exception to throw; normally {@code java.lang.NullPointerException}.
|
||||
*/
|
||||
public static JCStatement generateNullCheck(JavacTreeMaker maker, JavacNode variable) {
|
||||
public static JCStatement generateNullCheck(JavacTreeMaker maker, JavacNode variable, JavacNode source) {
|
||||
String exceptionType = source.getAst().readConfiguration(ConfigurationKeys.NON_NULL_EXCEPTION_TYPE);
|
||||
if (exceptionType == null) {
|
||||
exceptionType = HandlerUtil.DEFAULT_EXCEPTION_FOR_NON_NULL;
|
||||
} else {
|
||||
if (!HandlerUtil.isLegalBasicClassReference(exceptionType)) {
|
||||
source.addWarning("Configuration key contains invalid java type reference '" + exceptionType + "'; use something like 'java.lang.NullPointerException' as value for this key.");
|
||||
exceptionType = HandlerUtil.DEFAULT_EXCEPTION_FOR_NON_NULL;
|
||||
}
|
||||
}
|
||||
|
||||
JCVariableDecl varDecl = (JCVariableDecl) variable.get();
|
||||
if (isPrimitive(varDecl.vartype)) return null;
|
||||
Name fieldName = varDecl.name;
|
||||
JCExpression npe = genJavaLangTypeRef(variable, "NullPointerException");
|
||||
JCExpression exception = maker.NewClass(null, List.<JCExpression>nil(), npe, List.<JCExpression>of(maker.Literal(fieldName.toString())), null);
|
||||
JCExpression exType = genTypeRef(variable, exceptionType);
|
||||
JCExpression exception = maker.NewClass(null, List.<JCExpression>nil(), exType, List.<JCExpression>of(maker.Literal(fieldName.toString())), null);
|
||||
JCStatement throwStatement = maker.Throw(exception);
|
||||
JCBlock throwBlock = maker.Block(0, List.of(throwStatement));
|
||||
return maker.If(maker.Binary(CTC_EQUAL, maker.Ident(fieldName), maker.Literal(CTC_BOT, null)), throwBlock, null);
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
public class NonNullWithAlternateException {
|
||||
@lombok.NonNull
|
||||
private String test;
|
||||
public void testMethod(@lombok.NonNull String arg) {
|
||||
if (arg == null) {
|
||||
throw new java.lang.IllegalArgumentException("arg");
|
||||
}
|
||||
System.out.println(arg);
|
||||
}
|
||||
@java.lang.SuppressWarnings("all")
|
||||
public void setTest(@lombok.NonNull final String test) {
|
||||
if (test == null) {
|
||||
throw new java.lang.IllegalArgumentException("test");
|
||||
}
|
||||
this.test = test;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
public class NonNullWithAlternateException {
|
||||
private @lombok.NonNull @lombok.Setter String test;
|
||||
public NonNullWithAlternateException() {
|
||||
super();
|
||||
}
|
||||
public void testMethod(@lombok.NonNull String arg) {
|
||||
if ((arg == null))
|
||||
{
|
||||
throw new java.lang.IllegalArgumentException("arg");
|
||||
}
|
||||
System.out.println(arg);
|
||||
}
|
||||
public @java.lang.SuppressWarnings("all") void setTest(final @lombok.NonNull String test) {
|
||||
if ((test == null))
|
||||
{
|
||||
throw new java.lang.IllegalArgumentException("test");
|
||||
}
|
||||
this.test = test;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
//CONF: lombok.nonNull.exceptionType = java.lang.IllegalArgumentException
|
||||
|
||||
public class NonNullWithAlternateException {
|
||||
@lombok.NonNull @lombok.Setter private String test;
|
||||
|
||||
public void testMethod(@lombok.NonNull String arg) {
|
||||
System.out.println(arg);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
//CONF: lombok.nonNull.exceptionType = 12345
|
||||
//skip compare content: Just testing appropriate generation of error message.
|
||||
|
||||
@lombok.Data
|
||||
public class NonNullWithMistypedException {
|
||||
private @lombok.NonNull String test;
|
||||
}
|
||||
@@ -1 +1 @@
|
||||
8 @NonNull is meaningless on a primitive.
|
||||
5 @NonNull is meaningless on a primitive.
|
||||
@@ -0,0 +1 @@
|
||||
4 Configuration key contains invalid java type reference '12345'; use something like 'java.lang.NullPointerException' as value for this key.
|
||||
@@ -0,0 +1 @@
|
||||
4 Configuration key contains invalid java type reference '12345'; use something like 'java.lang.NullPointerException' as value for this key.
|
||||
@@ -42,6 +42,8 @@
|
||||
<div class="overview confKeys">
|
||||
<h3>Supported configuration keys:</h3>
|
||||
<dl>
|
||||
<dt><code>lombok.nonNull.exceptionType</code> = [<code>fully qualified name of an exception</code>] (default: <code>java.lang.NullPointerException</code>).
|
||||
<dd>When lombok generates a null-check <code>if</code> statement, an exception is thrown, with the parameter / field name as message. By default, this will be a <code>java.lang.NullPointerException</code>, but you can for example put <code>java.lang.IllegalArgumentException</code> in this configuration key to have lombok throw a different exception.</dd>
|
||||
<dt><code>lombok.nonNull.flagUsage</code> = [<code>warning</code> | <code>error</code>] (default: not set)</dt>
|
||||
<dd>Lombok will flag any usage of <code>@NonNull</code> as a warning or error if configured.</dd>
|
||||
</dl>
|
||||
|
||||
Reference in new issue
Block a user