aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/changelog.markdown6
-rw-r--r--src/core/lombok/ConfigurationKeys.java8
-rw-r--r--src/core/lombok/core/handlers/HandlerUtil.java12
-rw-r--r--src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java2
-rw-r--r--src/core/lombok/eclipse/handlers/HandleFieldNameConstants.java107
-rw-r--r--src/core/lombok/experimental/FieldNameConstants.java11
-rw-r--r--src/core/lombok/javac/handlers/HandleFieldNameConstants.java78
-rw-r--r--test/core/src/lombok/AbstractRunTests.java2
-rw-r--r--test/transform/resource/after-delombok/EqualsAndHashCodeWithGenericsOnInners.java1
-rw-r--r--test/transform/resource/after-delombok/FieldNameConstantsBasic.java8
-rw-r--r--test/transform/resource/after-delombok/FieldNameConstantsWeird.java4
-rw-r--r--test/transform/resource/after-delombok/InnerClass.java3
-rw-r--r--test/transform/resource/after-ecj/FieldNameConstantsBasic.java15
-rw-r--r--test/transform/resource/after-ecj/FieldNameConstantsWeird.java9
-rw-r--r--test/transform/resource/before/FieldNameConstantsBasic.java11
-rw-r--r--test/transform/resource/before/FieldNameConstantsWeird.java9
-rw-r--r--test/transform/resource/messages-delombok/FieldNameConstantsWeird.java.messages1
-rw-r--r--test/transform/resource/messages-ecj/FieldNameConstantsWeird.java.messages1
-rw-r--r--usage_examples/experimental/FieldNameConstantsExample_post.jpage7
-rw-r--r--usage_examples/experimental/FieldNameConstantsExample_pre.jpage9
-rw-r--r--website/templates/features/experimental/FieldNameConstants.html44
-rw-r--r--website/templates/features/experimental/index.html4
22 files changed, 222 insertions, 130 deletions
diff --git a/doc/changelog.markdown b/doc/changelog.markdown
index 9e84afb8..51da4651 100644
--- a/doc/changelog.markdown
+++ b/doc/changelog.markdown
@@ -3,9 +3,11 @@ Lombok Changelog
### v1.16.21 "Edgy Guinea Pig"
* v1.16.20 is the latest stable release of Project Lombok.
+* FEATURE: `@FieldNameConstants` is an new feature that generates string constants for your field names. [Docs on @FieldNameConstants](https://projectlombok.org/features/experimental/FieldNameConstants).
* PLATFORM: Fix for using lombok together with JDK9's new `module-info.java` feature. [Issue #985](https://github.com/rzwitserloot/lombok/issues/985)
-* PLATFORM: Some initial work on supporting JDK10.
-* BUGFIX: Potential fix for Netbeans < 9. [Issue #1555](https://github.com/rzwitserloot/lombok/issues/1555)
+* PLATFORM: Some initial work on supporting JDK10 and JDK11.
+* BUGFIX: Solved some issues in eclipse that resulted in error 'A save participant caused problems'. [Issue #879](https://github.com/rzwitserloot/lombok/issues/879)
+* BUGFIX: Bugfix for Netbeans < 9. [Issue #1555](https://github.com/rzwitserloot/lombok/issues/1555)
* PROMOTION: `var` has been promoted from experimental to the main package with no changes. The 'old' experimental one is still around but is deprecated, and is an alias for the new main package one. [var documentation](https://projectlombok.org/features/var.html).
* OLD-CRUFT: `lombok.experimental.Builder` and `lombok.experimental.Value` are deprecated remnants of when these features were still in experimental. They are now removed entirely. If your project is dependent on an older version of lombok which still has those; fret not, lombok still processes these annotations. It just no longer includes them in the jar.
diff --git a/src/core/lombok/ConfigurationKeys.java b/src/core/lombok/ConfigurationKeys.java
index 29c43d3f..7efe20bd 100644
--- a/src/core/lombok/ConfigurationKeys.java
+++ b/src/core/lombok/ConfigurationKeys.java
@@ -499,6 +499,14 @@ public class ConfigurationKeys {
*/
public static final ConfigurationKey<FlagUsageType> UTILITY_CLASS_FLAG_USAGE = new ConfigurationKey<FlagUsageType>("lombok.utilityClass.flagUsage", "Emit a warning or error if @UtilityClass is used.") {};
+ // ----- FieldNameConstants -----
+ /**
+ * lombok configuration: {@code lombok.fieldNameConstants.flagUsage} = {@code WARNING} | {@code ERROR}.
+ *
+ * If set, <em>any</em> usage of {@code @FieldNameConstants} results in a warning / error.
+ */
+ public static final ConfigurationKey<FlagUsageType> FIELD_NAME_CONSTANTS_FLAG_USAGE = new ConfigurationKey<FlagUsageType>("lombok.fieldNameConstants.flagUsage", "Emit a warning or error if @FieldNameConstants is used.") {};
+
// ----- Wither -----
/**
diff --git a/src/core/lombok/core/handlers/HandlerUtil.java b/src/core/lombok/core/handlers/HandlerUtil.java
index 6b516904..211b4924 100644
--- a/src/core/lombok/core/handlers/HandlerUtil.java
+++ b/src/core/lombok/core/handlers/HandlerUtil.java
@@ -441,4 +441,16 @@ public class HandlerUtil {
}
return String.format("%s%s", prefix, suffix);
}
+
+ public static String camelCaseToConstant(String fieldName) {
+ if (fieldName == null || fieldName.isEmpty()) return "";
+ StringBuilder b = new StringBuilder();
+ b.append(Character.toUpperCase(fieldName.charAt(0)));
+ for (int i = 1; i < fieldName.length(); i++) {
+ char c = fieldName.charAt(i);
+ if (Character.isUpperCase(c)) b.append('_');
+ b.append(Character.toUpperCase(c));
+ }
+ return b.toString();
+ }
}
diff --git a/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java b/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java
index 6617d21a..c49107e5 100644
--- a/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java
+++ b/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java
@@ -1097,7 +1097,7 @@ public class EclipseHandlerUtil {
public static boolean filterField(FieldDeclaration declaration, boolean skipStatic) {
// Skip the fake fields that represent enum constants.
if (declaration.initialization instanceof AllocationExpression &&
- ((AllocationExpression)declaration.initialization).enumConstant != null) return false;
+ ((AllocationExpression) declaration.initialization).enumConstant != null) return false;
if (declaration.type == null) return false;
diff --git a/src/core/lombok/eclipse/handlers/HandleFieldNameConstants.java b/src/core/lombok/eclipse/handlers/HandleFieldNameConstants.java
index 597b0937..754ddf47 100644
--- a/src/core/lombok/eclipse/handlers/HandleFieldNameConstants.java
+++ b/src/core/lombok/eclipse/handlers/HandleFieldNameConstants.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012-2014 The Project Lombok Authors.
+ * Copyright (C) 2014-2018 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
@@ -21,15 +21,17 @@
*/
package lombok.eclipse.handlers;
-import static java.lang.Character.*;
+import static lombok.core.handlers.HandlerUtil.handleExperimentalFlagUsage;
import static lombok.eclipse.handlers.EclipseHandlerUtil.*;
import java.lang.reflect.Modifier;
import java.util.Collection;
import lombok.AccessLevel;
+import lombok.ConfigurationKeys;
import lombok.core.AST.Kind;
import lombok.core.AnnotationValues;
+import lombok.core.handlers.HandlerUtil;
import lombok.eclipse.Eclipse;
import lombok.eclipse.EclipseAnnotationHandler;
import lombok.eclipse.EclipseNode;
@@ -45,16 +47,9 @@ import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
import org.mangosdk.spi.ProviderFor;
-@ProviderFor(EclipseAnnotationHandler.class) public class HandleFieldNameConstants extends EclipseAnnotationHandler<FieldNameConstants> {
-
- public boolean generateFieldDefaultsForType(EclipseNode typeNode, EclipseNode errorNode, AccessLevel level, boolean checkForTypeLevelFieldNameConstants) {
-
- if (checkForTypeLevelFieldNameConstants) {
- if (hasAnnotation(FieldNameConstants.class, typeNode)) {
- return true;
- }
- }
-
+@ProviderFor(EclipseAnnotationHandler.class)
+public class HandleFieldNameConstants extends EclipseAnnotationHandler<FieldNameConstants> {
+ public void generateFieldNameConstantsForType(EclipseNode typeNode, EclipseNode errorNode, AccessLevel level) {
TypeDeclaration typeDecl = null;
if (typeNode.get() instanceof TypeDeclaration) typeDecl = (TypeDeclaration) typeNode.get();
@@ -62,45 +57,20 @@ import org.mangosdk.spi.ProviderFor;
boolean notAClass = (modifiers & (ClassFileConstants.AccInterface | ClassFileConstants.AccAnnotation)) != 0;
if (typeDecl == null || notAClass) {
- errorNode.addError("@FieldNameConstants is only supported on a class or an enum or a field.");
- return false;
+ errorNode.addError("@FieldNameConstants is only supported on a class, an enum, or a field.");
+ return;
}
for (EclipseNode field : typeNode.down()) {
if (fieldQualifiesForFieldNameConstantsGeneration(field)) generateFieldNameConstantsForField(field, errorNode.get(), level);
- if (field.getKind() != Kind.FIELD) return false;
}
- return true;
}
private void generateFieldNameConstantsForField(EclipseNode fieldNode, ASTNode pos, AccessLevel level) {
- if (hasAnnotation(FieldNameConstants.class, fieldNode)) {
- return;
- }
+ if (hasAnnotation(FieldNameConstants.class, fieldNode)) return;
createFieldNameConstantsForField(level, fieldNode, fieldNode, pos, false);
}
- private void createFieldNameConstantsForField(AccessLevel level, EclipseNode fieldNode, EclipseNode errorNode, ASTNode source, boolean whineIfExists) {
- if (fieldNode.getKind() != Kind.FIELD) {
- errorNode.addError("@FieldNameConstants is only supported on a class or a field");
- return;
- }
- FieldDeclaration field = (FieldDeclaration) fieldNode.get();
- String constantName = camelCaseToConstant(new String(field.name));
- if (constantName == null) {
- errorNode.addWarning("Not generating constant for this field: It does not fit in your @Accessors prefix list");
- return;
- }
- int pS = source.sourceStart, pE = source.sourceEnd;
- long p = (long) pS << 32 | pE;
- FieldDeclaration fieldConstant = new FieldDeclaration(constantName.toCharArray(), pS,pE);
- fieldConstant.bits |= Eclipse.ECLIPSE_DO_NOT_TOUCH_FLAG;
- fieldConstant.modifiers = toEclipseModifier(level) | Modifier.STATIC | Modifier.FINAL;
- fieldConstant.type = new QualifiedTypeReference(TypeConstants.JAVA_LANG_STRING, new long[]{p,p,p});
- fieldConstant.initialization = new StringLiteral(field.name, pS,pE,0);
- injectField(fieldNode.up(), fieldConstant);
- }
-
private boolean fieldQualifiesForFieldNameConstantsGeneration(EclipseNode field) {
if (field.getKind() != Kind.FIELD) return false;
FieldDeclaration fieldDecl = (FieldDeclaration) field.get();
@@ -108,43 +78,52 @@ import org.mangosdk.spi.ProviderFor;
}
public void handle(AnnotationValues<FieldNameConstants> annotation, Annotation ast, EclipseNode annotationNode) {
+ handleExperimentalFlagUsage(annotationNode, ConfigurationKeys.FIELD_NAME_CONSTANTS_FLAG_USAGE, "@FieldNameConstants");
+
EclipseNode node = annotationNode.up();
FieldNameConstants annotatationInstance = annotation.getInstance();
AccessLevel level = annotatationInstance.level();
if (node == null) return;
- switch (node.getKind()){
+
+ switch (node.getKind()) {
case FIELD:
- createFieldNameConstantsForFields(level, annotationNode.upFromAnnotationToFields(), annotationNode, annotationNode.get(), true);
+ if (level != AccessLevel.NONE) createFieldNameConstantsForFields(level, annotationNode.upFromAnnotationToFields(), annotationNode, annotationNode.get(), true);
break;
case TYPE:
- generateFieldDefaultsForType(node, annotationNode, level, false);
+ if (level == AccessLevel.NONE) {
+ annotationNode.addWarning("type-level '@FieldNameConstants' does not work with AccessLevel.NONE.");
+ return;
+ }
+ generateFieldNameConstantsForType(node, annotationNode, level);
break;
-
}
-
}
private void createFieldNameConstantsForFields(AccessLevel level, Collection<EclipseNode> fieldNodes, EclipseNode errorNode, ASTNode source, boolean whineIfExists) {
- for (EclipseNode fieldNode : fieldNodes){
- createFieldNameConstantsForField(level, fieldNode, errorNode, source, whineIfExists);
- }
+ for (EclipseNode fieldNode : fieldNodes) createFieldNameConstantsForField(level, fieldNode, errorNode, source, whineIfExists);
}
-
- public static String camelCaseToConstant(final String fieldName) {
- if (fieldName == null || fieldName.isEmpty()) return "";
- char[] chars = fieldName.toCharArray();
- StringBuilder b = new StringBuilder();
- b.append(toUpperCase(chars[0]));
- for (int i = 1, iend = chars.length; i < iend; i++) {
- char c = chars[i];
- if (isUpperCase(c)) {
- b.append('_');
- } else {
- c = toUpperCase(c);
- }
- b.append(c);
+
+ private void createFieldNameConstantsForField(AccessLevel level, EclipseNode fieldNode, EclipseNode errorNode, ASTNode source, boolean whineIfExists) {
+ if (fieldNode.getKind() != Kind.FIELD) {
+ errorNode.addError("@FieldNameConstants is only supported on a class, an enum, or a field");
+ return;
}
- return b.toString();
+
+ FieldDeclaration field = (FieldDeclaration) fieldNode.get();
+ String fieldName = new String(field.name);
+ String constantName = HandlerUtil.camelCaseToConstant(fieldName);
+ if (constantName.equals(fieldName)) {
+ fieldNode.addWarning("Not generating constant for this field: The name of the constant would be equal to the name of this field.");
+ return;
+ }
+
+ int pS = source.sourceStart, pE = source.sourceEnd;
+ long p = (long) pS << 32 | pE;
+ FieldDeclaration fieldConstant = new FieldDeclaration(constantName.toCharArray(), pS,pE);
+ fieldConstant.bits |= Eclipse.ECLIPSE_DO_NOT_TOUCH_FLAG;
+ fieldConstant.modifiers = toEclipseModifier(level) | Modifier.STATIC | Modifier.FINAL;
+ fieldConstant.type = new QualifiedTypeReference(TypeConstants.JAVA_LANG_STRING, new long[] {p,p,p});
+ fieldConstant.initialization = new StringLiteral(field.name, pS, pE, 0);
+ injectField(fieldNode.up(), fieldConstant);
}
-
}
diff --git a/src/core/lombok/experimental/FieldNameConstants.java b/src/core/lombok/experimental/FieldNameConstants.java
index 0f582f18..41b33ac7 100644
--- a/src/core/lombok/experimental/FieldNameConstants.java
+++ b/src/core/lombok/experimental/FieldNameConstants.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009-2013 The Project Lombok Authors.
+ * Copyright (C) 2014-2018 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
@@ -28,16 +28,11 @@ import java.lang.annotation.Target;
import lombok.AccessLevel;
-
-
-
/**
* Generates String constants containing the field name for each field.
- *
*/
-@Target(ElementType.TYPE)
+@Target({ElementType.TYPE, ElementType.FIELD})
@Retention(RetentionPolicy.SOURCE)
public @interface FieldNameConstants {
-
- lombok.AccessLevel level()default AccessLevel.PUBLIC;
+ lombok.AccessLevel level() default AccessLevel.PUBLIC;
}
diff --git a/src/core/lombok/javac/handlers/HandleFieldNameConstants.java b/src/core/lombok/javac/handlers/HandleFieldNameConstants.java
index cf0fad0c..089d225d 100644
--- a/src/core/lombok/javac/handlers/HandleFieldNameConstants.java
+++ b/src/core/lombok/javac/handlers/HandleFieldNameConstants.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012-2014 The Project Lombok Authors.
+ * Copyright (C) 2014-2018 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
@@ -21,13 +21,16 @@
*/
package lombok.javac.handlers;
+import static lombok.core.handlers.HandlerUtil.handleExperimentalFlagUsage;
import static lombok.javac.handlers.JavacHandlerUtil.*;
import java.lang.reflect.Modifier;
import java.util.Collection;
import lombok.AccessLevel;
+import lombok.ConfigurationKeys;
import lombok.core.AST.Kind;
+import lombok.core.handlers.HandlerUtil;
import lombok.core.AnnotationValues;
import lombok.experimental.FieldNameConstants;
import lombok.javac.JavacAnnotationHandler;
@@ -43,18 +46,10 @@ import com.sun.tools.javac.tree.JCTree.JCExpression;
import com.sun.tools.javac.tree.JCTree.JCModifiers;
import com.sun.tools.javac.tree.JCTree.JCVariableDecl;
import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
-import com.sun.tools.javac.util.List;
-@ProviderFor(JavacAnnotationHandler.class) @SuppressWarnings("restriction") public class HandleFieldNameConstants extends JavacAnnotationHandler<FieldNameConstants> {
-
- public void generateFieldDefaultsForType(JavacNode typeNode, JavacNode errorNode, AccessLevel level, boolean checkForTypeLevelFieldNameConstants) {
-
- if (checkForTypeLevelFieldNameConstants) {
- if (hasAnnotation(FieldNameConstants.class, typeNode)) {
- return;
- }
- }
-
+@ProviderFor(JavacAnnotationHandler.class)
+public class HandleFieldNameConstants extends JavacAnnotationHandler<FieldNameConstants> {
+ public void generateFieldNameConstantsForType(JavacNode typeNode, JavacNode errorNode, AccessLevel level) {
JCClassDecl typeDecl = null;
if (typeNode.get() instanceof JCClassDecl) typeDecl = (JCClassDecl) typeNode.get();
@@ -62,21 +57,18 @@ import com.sun.tools.javac.util.List;
boolean notAClass = (modifiers & (Flags.INTERFACE | Flags.ANNOTATION)) != 0;
if (typeDecl == null || notAClass) {
- errorNode.addError("@FieldNameConstants is only supported on a class or an enum or a field.");
+ errorNode.addError("@FieldNameConstants is only supported on a class, an enum, or a field.");
return;
}
for (JavacNode field : typeNode.down()) {
if (fieldQualifiesForFieldNameConstantsGeneration(field)) generateFieldNameConstantsForField(field, errorNode.get(), level);
-
}
}
private void generateFieldNameConstantsForField(JavacNode fieldNode, DiagnosticPosition pos, AccessLevel level) {
- if (hasAnnotation(FieldNameConstants.class, fieldNode)) {
- return;
- }
- createFieldNameConstantsForField(level, fieldNode, fieldNode, false, List.<JCAnnotation>nil());
+ if (hasAnnotation(FieldNameConstants.class, fieldNode)) return;
+ createFieldNameConstantsForField(level, fieldNode, fieldNode, false);
}
private boolean fieldQualifiesForFieldNameConstantsGeneration(JavacNode field) {
@@ -88,6 +80,7 @@ import com.sun.tools.javac.util.List;
}
public void handle(AnnotationValues<FieldNameConstants> annotation, JCAnnotation ast, JavacNode annotationNode) {
+ handleExperimentalFlagUsage(annotationNode, ConfigurationKeys.FIELD_NAME_CONSTANTS_FLAG_USAGE, "@FieldNameConstants");
Collection<JavacNode> fields = annotationNode.upFromAnnotationToFields();
deleteAnnotationIfNeccessary(annotationNode, FieldNameConstants.class);
@@ -95,40 +88,36 @@ import com.sun.tools.javac.util.List;
JavacNode node = annotationNode.up();
FieldNameConstants annotatationInstance = annotation.getInstance();
AccessLevel level = annotatationInstance.level();
- if (level == AccessLevel.NONE) {
- annotationNode.addWarning("'lazy' does not work with AccessLevel.NONE.");
- return;
- }
if (node == null) return;
- List<JCAnnotation> onMethod = unboxAndRemoveAnnotationParameter(ast, "onMethod", "@FieldNameConstants(onMethod=", annotationNode);
switch (node.getKind()) {
case FIELD:
- createFieldNameConstantsForFields(level, fields, annotationNode, annotationNode, true, onMethod);
+ if (level != AccessLevel.NONE) createFieldNameConstantsForFields(level, fields, annotationNode, annotationNode, true);
break;
case TYPE:
- if (!onMethod.isEmpty()) {
- annotationNode.addError("'onMethod' is not supported for @FieldNameConstants on a type.");
+ if (level == AccessLevel.NONE) {
+ annotationNode.addWarning("type-level '@FieldNameConstants' does not work with AccessLevel.NONE.");
+ return;
}
- generateFieldDefaultsForType(node, annotationNode, level, false);
+ generateFieldNameConstantsForType(node, annotationNode, level);
break;
}
}
- private void createFieldNameConstantsForFields(AccessLevel level, Collection<JavacNode> fieldNodes, JavacNode annotationNode, JavacNode errorNode, boolean whineIfExists, List<JCAnnotation> onMethod) {
- for (JavacNode fieldNode : fieldNodes) {
- createFieldNameConstantsForField(level, fieldNode, errorNode, whineIfExists, onMethod);
- }
+ private void createFieldNameConstantsForFields(AccessLevel level, Collection<JavacNode> fieldNodes, JavacNode annotationNode, JavacNode errorNode, boolean whineIfExists) {
+ for (JavacNode fieldNode : fieldNodes) createFieldNameConstantsForField(level, fieldNode, errorNode, whineIfExists);
}
- private void createFieldNameConstantsForField(AccessLevel level, JavacNode fieldNode, JavacNode source, boolean whineIfExists, List<JCAnnotation> onMethod) {
+ private void createFieldNameConstantsForField(AccessLevel level, JavacNode fieldNode, JavacNode source, boolean whineIfExists) {
if (fieldNode.getKind() != Kind.FIELD) {
- source.addError("@FieldNameConstants is only supported on a class or a field");
+ source.addError("@FieldNameConstants is only supported on a class, an enum, or a field");
return;
}
+
JCVariableDecl field = (JCVariableDecl) fieldNode.get();
- String constantName = camelCaseToConstant(field.name.toString());
- if (constantName == null) {
- source.addWarning("Not generating constant for this field: It does not fit in your @Accessors prefix list");
+ String fieldName = field.name.toString();
+ String constantName = HandlerUtil.camelCaseToConstant(fieldName);
+ if (constantName.equals(fieldName)) {
+ fieldNode.addWarning("Not generating constant for this field: The name of the constant would be equal to the name of this field.");
return;
}
@@ -139,21 +128,4 @@ import com.sun.tools.javac.util.List;
JCVariableDecl fieldConstant = treeMaker.VarDef(modifiers, fieldNode.toName(constantName), returnType, init);
injectField(fieldNode.up(), fieldConstant);
}
-
- public static String camelCaseToConstant(final String fieldName) {
- if (fieldName == null || fieldName.isEmpty()) return "";
- char[] chars = fieldName.toCharArray();
- StringBuilder b = new StringBuilder();
- b.append(Character.toUpperCase(chars[0]));
- for (int i = 1, iend = chars.length; i < iend; i++) {
- char c = chars[i];
- if (Character.isUpperCase(c)) {
- b.append('_');
- } else {
- c = Character.toUpperCase(c);
- }
- b.append(c);
- }
- return b.toString();
- }
} \ No newline at end of file
diff --git a/test/core/src/lombok/AbstractRunTests.java b/test/core/src/lombok/AbstractRunTests.java
index 1a454585..3d672bc4 100644
--- a/test/core/src/lombok/AbstractRunTests.java
+++ b/test/core/src/lombok/AbstractRunTests.java
@@ -243,7 +243,7 @@ public abstract class AbstractRunTests {
int size = Math.min(expectedLines.length, actualLines.length);
if (size == 0 && expectedLines.length + actualLines.length > 0) {
- Assert.fail("Missing / empty expected file.");
+ Assert.fail("Missing / empty expected file: " + name);
}
for (int i = 0; i < size; i++) {
diff --git a/test/transform/resource/after-delombok/EqualsAndHashCodeWithGenericsOnInners.java b/test/transform/resource/after-delombok/EqualsAndHashCodeWithGenericsOnInners.java
index 501d45a1..9eb3cdb3 100644
--- a/test/transform/resource/after-delombok/EqualsAndHashCodeWithGenericsOnInners.java
+++ b/test/transform/resource/after-delombok/EqualsAndHashCodeWithGenericsOnInners.java
@@ -1,3 +1,4 @@
+//version 7:
public class EqualsAndHashCodeWithGenericsOnInners<A> {
class Inner<B> {
int x;
diff --git a/test/transform/resource/after-delombok/FieldNameConstantsBasic.java b/test/transform/resource/after-delombok/FieldNameConstantsBasic.java
new file mode 100644
index 00000000..de5d68c6
--- /dev/null
+++ b/test/transform/resource/after-delombok/FieldNameConstantsBasic.java
@@ -0,0 +1,8 @@
+public class FieldNameConstantsBasic {
+ protected static final java.lang.String I_AM_A_DVD_PLAYER = "iAmADvdPlayer";
+ public static final java.lang.String BUT_PRINT_ME_PLEASE = "butPrintMePlease";
+ String iAmADvdPlayer;
+ int $skipMe;
+ static double skipMeToo;
+ String butPrintMePlease;
+}
diff --git a/test/transform/resource/after-delombok/FieldNameConstantsWeird.java b/test/transform/resource/after-delombok/FieldNameConstantsWeird.java
new file mode 100644
index 00000000..a256f5ba
--- /dev/null
+++ b/test/transform/resource/after-delombok/FieldNameConstantsWeird.java
@@ -0,0 +1,4 @@
+public class FieldNameConstantsWeird {
+ String iAmADvdPlayer;
+ String X;
+}
diff --git a/test/transform/resource/after-delombok/InnerClass.java b/test/transform/resource/after-delombok/InnerClass.java
index 6d42bb79..2e49b9ad 100644
--- a/test/transform/resource/after-delombok/InnerClass.java
+++ b/test/transform/resource/after-delombok/InnerClass.java
@@ -1,3 +1,4 @@
+//version 8:
class A {
class B {
String s;
@@ -48,4 +49,4 @@ class C {
return "C.D(a=" + this.getA() + ")";
}
}
-} \ No newline at end of file
+}
diff --git a/test/transform/resource/after-ecj/FieldNameConstantsBasic.java b/test/transform/resource/after-ecj/FieldNameConstantsBasic.java
new file mode 100644
index 00000000..bfa339fb
--- /dev/null
+++ b/test/transform/resource/after-ecj/FieldNameConstantsBasic.java
@@ -0,0 +1,15 @@
+import lombok.experimental.FieldNameConstants;
+import lombok.AccessLevel;
+public @FieldNameConstants class FieldNameConstantsBasic {
+ public static final java.lang.String BUT_PRINT_ME_PLEASE = "butPrintMePlease";
+ protected static final java.lang.String I_AM_A_DVD_PLAYER = "iAmADvdPlayer";
+ @FieldNameConstants(level = AccessLevel.PROTECTED) String iAmADvdPlayer;
+ int $skipMe;
+ static double skipMeToo;
+ String butPrintMePlease;
+ <clinit>() {
+ }
+ public FieldNameConstantsBasic() {
+ super();
+ }
+}
diff --git a/test/transform/resource/after-ecj/FieldNameConstantsWeird.java b/test/transform/resource/after-ecj/FieldNameConstantsWeird.java
new file mode 100644
index 00000000..c581b7ef
--- /dev/null
+++ b/test/transform/resource/after-ecj/FieldNameConstantsWeird.java
@@ -0,0 +1,9 @@
+import lombok.experimental.FieldNameConstants;
+import lombok.AccessLevel;
+public @FieldNameConstants class FieldNameConstantsWeird {
+ @FieldNameConstants(level = AccessLevel.NONE) String iAmADvdPlayer;
+ String X;
+ public FieldNameConstantsWeird() {
+ super();
+ }
+}
diff --git a/test/transform/resource/before/FieldNameConstantsBasic.java b/test/transform/resource/before/FieldNameConstantsBasic.java
new file mode 100644
index 00000000..1bc15d84
--- /dev/null
+++ b/test/transform/resource/before/FieldNameConstantsBasic.java
@@ -0,0 +1,11 @@
+import lombok.experimental.FieldNameConstants;
+import lombok.AccessLevel;
+
+@FieldNameConstants
+public class FieldNameConstantsBasic {
+ @FieldNameConstants(level = AccessLevel.PROTECTED)
+ String iAmADvdPlayer;
+ int $skipMe;
+ static double skipMeToo;
+ String butPrintMePlease;
+}
diff --git a/test/transform/resource/before/FieldNameConstantsWeird.java b/test/transform/resource/before/FieldNameConstantsWeird.java
new file mode 100644
index 00000000..0f99133d
--- /dev/null
+++ b/test/transform/resource/before/FieldNameConstantsWeird.java
@@ -0,0 +1,9 @@
+import lombok.experimental.FieldNameConstants;
+import lombok.AccessLevel;
+
+@FieldNameConstants
+public class FieldNameConstantsWeird {
+ @FieldNameConstants(level = AccessLevel.NONE)
+ String iAmADvdPlayer;
+ String X;
+}
diff --git a/test/transform/resource/messages-delombok/FieldNameConstantsWeird.java.messages b/test/transform/resource/messages-delombok/FieldNameConstantsWeird.java.messages
new file mode 100644
index 00000000..d5fc44f5
--- /dev/null
+++ b/test/transform/resource/messages-delombok/FieldNameConstantsWeird.java.messages
@@ -0,0 +1 @@
+8 Not generating constant for this field: The name of the constant would be equal to the name of this field.
diff --git a/test/transform/resource/messages-ecj/FieldNameConstantsWeird.java.messages b/test/transform/resource/messages-ecj/FieldNameConstantsWeird.java.messages
new file mode 100644
index 00000000..d5fc44f5
--- /dev/null
+++ b/test/transform/resource/messages-ecj/FieldNameConstantsWeird.java.messages
@@ -0,0 +1 @@
+8 Not generating constant for this field: The name of the constant would be equal to the name of this field.
diff --git a/usage_examples/experimental/FieldNameConstantsExample_post.jpage b/usage_examples/experimental/FieldNameConstantsExample_post.jpage
new file mode 100644
index 00000000..6300ed0e
--- /dev/null
+++ b/usage_examples/experimental/FieldNameConstantsExample_post.jpage
@@ -0,0 +1,7 @@
+public class FieldNameConstantsExample {
+ public static final String I_AM_A_FIELD = "iAmAField";
+ static final String AND_SO_AM_I = "andSoAmI";
+
+ private final String iAmAField;
+ private final int andSoAmI;
+}
diff --git a/usage_examples/experimental/FieldNameConstantsExample_pre.jpage b/usage_examples/experimental/FieldNameConstantsExample_pre.jpage
new file mode 100644
index 00000000..dc6376eb
--- /dev/null
+++ b/usage_examples/experimental/FieldNameConstantsExample_pre.jpage
@@ -0,0 +1,9 @@
+import lombok.experimental.FieldNameConstants;
+import lombok.AccessLevel;
+
+@FieldNameConstants
+public class FieldNameConstantsExample {
+ private final String iAmAField;
+ @FieldNameConstants(level = AccessLevel.PACKAGE)
+ private final int andSoAmI;
+}
diff --git a/website/templates/features/experimental/FieldNameConstants.html b/website/templates/features/experimental/FieldNameConstants.html
new file mode 100644
index 00000000..05c57f84
--- /dev/null
+++ b/website/templates/features/experimental/FieldNameConstants.html
@@ -0,0 +1,44 @@
+<#import "../_features.html" as f>
+
+<@f.scaffold title="@FieldNameConstants" logline="Name... that... field! String constants for your field's names.">
+ <@f.history>
+ <p>
+ @FieldNameConstants was introduced as experimental feature in lombok v2.0.0.
+ </p>
+ </@f.history>
+
+ <@f.experimental>
+ <ul>
+ <li>
+ New feature; unsure if this busts enough boilerplate.
+ </li>
+ </ul>
+ Current status: <em>neutral</em> - As a just-introduced feature we're still gathering feedback.
+ </@f.experimental>
+
+ <@f.overview>
+ <p>
+ The <code>@FieldNameConstants</code> annotation generates string constants (fields marked <code>public static final</code>, of type <code>java.lang.String</code>) containing the field's name, as a string. This is useful for various marshalling and serialization frameworks. The constant field has the same as the field it represents, except with all uppercase letters, with underscores in front of the uppercase letters in the original field. If this results in the exact same name, the constant is not generated (a warning is generated instead).
+ </p><p>
+ The <code>public</code> access modifier can be changed via the parameter <code>level = AccessLevel.PACKAGE</code> for example. You can force a field to be skipped by supplying <code>level = AccessLevel.NONE</code>.
+ </p><p>
+ Can be applied to classes (in which case every field gets a constant), or to an individual field.
+ </p>
+ </@f.overview>
+
+ <@f.snippets name="experimental/FieldNameConstants" />
+
+ <@f.confKeys>
+ <dt>
+ <code>lombok.fieldNameConstants.flagUsage</code> = [<code>warning</code> | <code>error</code>] (default: not set)
+ </dt><dd>
+ Lombok will flag any usage of <code>@FieldDefaults</code> as a warning or error if configured.
+ </dd>
+ </@f.confKeys>
+
+ <@f.smallPrint>
+ <p>
+ Like other lombok handlers that touch fields, any field whose name starts with a dollar (<code>$</code>) symbol is skipped entirely. Such a field will not be modified at all. Static fields are also skipped.
+ </p>
+ </@f.smallPrint>
+</@f.scaffold>
diff --git a/website/templates/features/experimental/index.html b/website/templates/features/experimental/index.html
index 21e8fceb..d9d67219 100644
--- a/website/templates/features/experimental/index.html
+++ b/website/templates/features/experimental/index.html
@@ -62,6 +62,10 @@
<@main.feature title="@Helper" href="Helper">
With a little help from my friends... Helper methods for java.
</@main.feature>
+
+ <@main.feature title="@FieldNameConstants" href="FieldNameConstants">
+ Name... that... field! String constants for your field's names.
+ </@main.feature>
</div>
<@f.confKeys>