diff options
8 files changed, 80 insertions, 11 deletions
diff --git a/doc/changelog.markdown b/doc/changelog.markdown index 614848cb..89ce9929 100644 --- a/doc/changelog.markdown +++ b/doc/changelog.markdown @@ -2,6 +2,7 @@ Lombok Changelog ---------------- ### v1.18.7 "Edgy Guinea Pig" +* FEATURE: You can now configure `@FieldNameConstants` to `CONSTANT_CASE` the generated constants, using a `lombok.config` option. See the [FieldNameConstants documentation](https://projectlombok.org/features/experimental/FieldNameConstants). [Issue #2092](https://github.com/rzwitserloot/lombok/issues/2092). * FEATURE: You can now suppress generation of the `builder` method when using `@Builder`; usually because you're only interested in the `toBuilder` method. As a convenience we won't emit warnings about missing `@Builder.Default` annotations when you do this. [Issue #2046](https://github.com/rzwitserloot/lombok/issues/2046) * FEATURE: You can now change the access modifier of generated builder classes. [Issue #2083](https://github.com/rzwitserloot/lombok/issues/2083). * FEATURE: When using `@NonNull`, or any other annotation that would result in a null-check, you can configure to generate an assert statement instead. [Issue #2078](https://github.com/rzwitserloot/lombok/issues/2078). diff --git a/src/core/lombok/ConfigurationKeys.java b/src/core/lombok/ConfigurationKeys.java index ad39f0af..84b594f5 100644 --- a/src/core/lombok/ConfigurationKeys.java +++ b/src/core/lombok/ConfigurationKeys.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013-2018 The Project Lombok Authors. + * Copyright (C) 2013-2019 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 @@ -543,6 +543,13 @@ public class ConfigurationKeys { */ public static final ConfigurationKey<String> FIELD_NAME_CONSTANTS_INNER_TYPE_NAME = new ConfigurationKey<String>("lombok.fieldNameConstants.innerTypeName", "The default name of the inner type generated by @FieldNameConstants. (default: 'Fields').") {}; + /** + * lombok configuration: {@code lombok.fieldNameConstants.uppercase} = {@code true} | {@code false}. + * + * If true, names of constants generated by {@code @FieldNameConstants} will be UPPER_CASED_LIKE_A_CONSTANT. (Default: {@code false}). + */ + public static final ConfigurationKey<Boolean> FIELD_NAME_CONSTANTS_UPPERCASE = new ConfigurationKey<Boolean>("lombok.fieldNameConstants.uppercase", "The default name of the constants inside the inner type generated by @FieldNameConstants follow the variable name precisely. If this config key is true, lombok will uppercase them as best it can. (default: false).") {}; + // ----- Wither ----- /** diff --git a/src/core/lombok/eclipse/handlers/HandleFieldNameConstants.java b/src/core/lombok/eclipse/handlers/HandleFieldNameConstants.java index 1caccd59..574c1f41 100644 --- a/src/core/lombok/eclipse/handlers/HandleFieldNameConstants.java +++ b/src/core/lombok/eclipse/handlers/HandleFieldNameConstants.java @@ -47,6 +47,7 @@ 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; @@ -55,7 +56,7 @@ import lombok.experimental.FieldNameConstants; @ProviderFor(EclipseAnnotationHandler.class) public class HandleFieldNameConstants extends EclipseAnnotationHandler<FieldNameConstants> { - public void generateFieldNameConstantsForType(EclipseNode typeNode, EclipseNode errorNode, AccessLevel level, boolean asEnum, String innerTypeName, boolean onlyExplicit) { + public void generateFieldNameConstantsForType(EclipseNode typeNode, EclipseNode errorNode, AccessLevel level, boolean asEnum, String innerTypeName, boolean onlyExplicit, boolean uppercase) { TypeDeclaration typeDecl = null; if (typeNode.get() instanceof TypeDeclaration) typeDecl = (TypeDeclaration) typeNode.get(); @@ -76,7 +77,7 @@ public class HandleFieldNameConstants extends EclipseAnnotationHandler<FieldName if (qualified.isEmpty()) { errorNode.addWarning("No fields qualify for @FieldNameConstants, therefore this annotation does nothing"); } else { - createInnerTypeFieldNameConstants(typeNode, errorNode, errorNode.get(), level, qualified, asEnum, innerTypeName); + createInnerTypeFieldNameConstants(typeNode, errorNode, errorNode.get(), level, qualified, asEnum, innerTypeName, uppercase); } } @@ -112,11 +113,13 @@ public class HandleFieldNameConstants extends EclipseAnnotationHandler<FieldName String innerTypeName = annotationInstance.innerTypeName(); if (innerTypeName.isEmpty()) innerTypeName = annotationNode.getAst().readConfiguration(ConfigurationKeys.FIELD_NAME_CONSTANTS_INNER_TYPE_NAME); if (innerTypeName == null || innerTypeName.isEmpty()) innerTypeName = "Fields"; + Boolean uppercase = annotationNode.getAst().readConfiguration(ConfigurationKeys.FIELD_NAME_CONSTANTS_UPPERCASE); + if (uppercase == null) uppercase = false; - generateFieldNameConstantsForType(node, annotationNode, level, asEnum, innerTypeName, annotationInstance.onlyExplicitlyIncluded()); + generateFieldNameConstantsForType(node, annotationNode, level, asEnum, innerTypeName, annotationInstance.onlyExplicitlyIncluded(), uppercase); } - private void createInnerTypeFieldNameConstants(EclipseNode typeNode, EclipseNode errorNode, ASTNode source, AccessLevel level, List<EclipseNode> fields, boolean asEnum, String innerTypeName) { + private void createInnerTypeFieldNameConstants(EclipseNode typeNode, EclipseNode errorNode, ASTNode source, AccessLevel level, List<EclipseNode> fields, boolean asEnum, String innerTypeName, boolean uppercase) { if (fields.isEmpty()) return; ASTVisitor generatedByVisitor = new SetGeneratedByVisitor(source); @@ -169,6 +172,7 @@ public class HandleFieldNameConstants extends EclipseAnnotationHandler<FieldName for (EclipseNode fieldNode : fields) { FieldDeclaration field = (FieldDeclaration) fieldNode.get(); char[] fName = field.name; + if (uppercase) fName = HandlerUtil.camelCaseToConstant(new String(fName)).toCharArray(); if (fieldExists(new String(fName), fieldsType) != MemberExistsResult.NOT_EXISTS) continue; int pS = source.sourceStart, pE = source.sourceEnd; long p = (long) pS << 32 | pE; diff --git a/src/core/lombok/javac/handlers/HandleFieldNameConstants.java b/src/core/lombok/javac/handlers/HandleFieldNameConstants.java index 4015df12..628e83dc 100644 --- a/src/core/lombok/javac/handlers/HandleFieldNameConstants.java +++ b/src/core/lombok/javac/handlers/HandleFieldNameConstants.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014-2018 The Project Lombok Authors. + * Copyright (C) 2014-2019 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 @@ -30,6 +30,7 @@ import lombok.AccessLevel; import lombok.ConfigurationKeys; import lombok.core.AST.Kind; import lombok.core.AnnotationValues; +import lombok.core.handlers.HandlerUtil; import lombok.experimental.FieldNameConstants; import lombok.javac.JavacAnnotationHandler; import lombok.javac.JavacNode; @@ -53,7 +54,7 @@ import com.sun.tools.javac.util.Name; @ProviderFor(JavacAnnotationHandler.class) public class HandleFieldNameConstants extends JavacAnnotationHandler<FieldNameConstants> { - public void generateFieldNameConstantsForType(JavacNode typeNode, JavacNode errorNode, AccessLevel level, boolean asEnum, String innerTypeName, boolean onlyExplicit) { + public void generateFieldNameConstantsForType(JavacNode typeNode, JavacNode errorNode, AccessLevel level, boolean asEnum, String innerTypeName, boolean onlyExplicit, boolean uppercase) { JCClassDecl typeDecl = null; if (typeNode.get() instanceof JCClassDecl) typeDecl = (JCClassDecl) typeNode.get(); @@ -74,7 +75,7 @@ public class HandleFieldNameConstants extends JavacAnnotationHandler<FieldNameCo if (qualified.isEmpty()) { errorNode.addWarning("No fields qualify for @FieldNameConstants, therefore this annotation does nothing"); } else { - createInnerTypeFieldNameConstants(typeNode, errorNode, errorNode.get(), level, qualified, asEnum, innerTypeName); + createInnerTypeFieldNameConstants(typeNode, errorNode, errorNode.get(), level, qualified, asEnum, innerTypeName, uppercase); } } @@ -117,11 +118,13 @@ public class HandleFieldNameConstants extends JavacAnnotationHandler<FieldNameCo String innerTypeName = annotationInstance.innerTypeName(); if (innerTypeName.isEmpty()) innerTypeName = annotationNode.getAst().readConfiguration(ConfigurationKeys.FIELD_NAME_CONSTANTS_INNER_TYPE_NAME); if (innerTypeName == null || innerTypeName.isEmpty()) innerTypeName = "Fields"; + Boolean uppercase = annotationNode.getAst().readConfiguration(ConfigurationKeys.FIELD_NAME_CONSTANTS_UPPERCASE); + if (uppercase == null) uppercase = false; - generateFieldNameConstantsForType(node, annotationNode, level, asEnum, innerTypeName, annotationInstance.onlyExplicitlyIncluded()); + generateFieldNameConstantsForType(node, annotationNode, level, asEnum, innerTypeName, annotationInstance.onlyExplicitlyIncluded(), uppercase); } - private void createInnerTypeFieldNameConstants(JavacNode typeNode, JavacNode errorNode, JCTree pos, AccessLevel level, java.util.List<JavacNode> fields, boolean asEnum, String innerTypeName) { + private void createInnerTypeFieldNameConstants(JavacNode typeNode, JavacNode errorNode, JCTree pos, AccessLevel level, java.util.List<JavacNode> fields, boolean asEnum, String innerTypeName, boolean uppercase) { if (fields.isEmpty()) return; JavacTreeMaker maker = typeNode.getTreeMaker(); @@ -161,6 +164,7 @@ public class HandleFieldNameConstants extends JavacAnnotationHandler<FieldNameCo java.util.List<JCVariableDecl> generated = new ArrayList<JCVariableDecl>(); for (JavacNode field : fields) { Name fName = ((JCVariableDecl) field.get()).name; + if (uppercase) fName = typeNode.toName(HandlerUtil.camelCaseToConstant(fName.toString())); if (fieldExists(fName.toString(), fieldsType) != MemberExistsResult.NOT_EXISTS) continue; JCModifiers constantValueMods = maker.Modifiers(Flags.PUBLIC | Flags.STATIC | Flags.FINAL | (asEnum ? Flags.ENUM : 0L)); JCExpression returnType; diff --git a/test/transform/resource/after-delombok/FieldNameConstantsUppercased.java b/test/transform/resource/after-delombok/FieldNameConstantsUppercased.java new file mode 100644 index 00000000..dd7de86a --- /dev/null +++ b/test/transform/resource/after-delombok/FieldNameConstantsUppercased.java @@ -0,0 +1,12 @@ +public class FieldNameConstantsUppercased { + String iAmADvdPlayer; + int $skipMe; + static double skipMeToo; + int andMe; + String butPrintMePlease; + @java.lang.SuppressWarnings("all") + static final class Fields { + public static final java.lang.String I_AM_A_DVD_PLAYER = "iAmADvdPlayer"; + public static final java.lang.String BUT_PRINT_ME_PLEASE = "butPrintMePlease"; + } +} diff --git a/test/transform/resource/after-ecj/FieldNameConstantsUppercased.java b/test/transform/resource/after-ecj/FieldNameConstantsUppercased.java new file mode 100644 index 00000000..a858b91f --- /dev/null +++ b/test/transform/resource/after-ecj/FieldNameConstantsUppercased.java @@ -0,0 +1,23 @@ +import lombok.experimental.FieldNameConstants; +import lombok.AccessLevel; +public @FieldNameConstants(level = AccessLevel.PACKAGE) class FieldNameConstantsUppercased { + static final @java.lang.SuppressWarnings("all") class Fields { + public static final java.lang.String I_AM_A_DVD_PLAYER = "iAmADvdPlayer"; + public static final java.lang.String BUT_PRINT_ME_PLEASE = "butPrintMePlease"; + <clinit>() { + } + private @java.lang.SuppressWarnings("all") Fields() { + super(); + } + } + String iAmADvdPlayer; + int $skipMe; + static double skipMeToo; + @FieldNameConstants.Exclude int andMe; + String butPrintMePlease; + <clinit>() { + } + public FieldNameConstantsUppercased() { + super(); + } +}
\ No newline at end of file diff --git a/test/transform/resource/before/FieldNameConstantsUppercased.java b/test/transform/resource/before/FieldNameConstantsUppercased.java new file mode 100644 index 00000000..674cb7f1 --- /dev/null +++ b/test/transform/resource/before/FieldNameConstantsUppercased.java @@ -0,0 +1,12 @@ +//CONF: lombok.fieldNameConstants.uppercase = true +import lombok.experimental.FieldNameConstants; +import lombok.AccessLevel; + +@FieldNameConstants(level = AccessLevel.PACKAGE) +public class FieldNameConstantsUppercased { + String iAmADvdPlayer; + int $skipMe; + static double skipMeToo; + @FieldNameConstants.Exclude int andMe; + String butPrintMePlease; +} diff --git a/website/templates/features/experimental/FieldNameConstants.html b/website/templates/features/experimental/FieldNameConstants.html index 1cbef32a..e88b7670 100644 --- a/website/templates/features/experimental/FieldNameConstants.html +++ b/website/templates/features/experimental/FieldNameConstants.html @@ -6,6 +6,8 @@ @FieldNameConstants was introduced as experimental feature in lombok v1.16.22. </p><p> @FieldNameConstants was redesigned in lombok v1.18.4. + </p><p> + The <em>lombok.config</em> option <code>lombok.fieldNameConstants.uppercase = true</code> was added in lombok v1.18.8. </p> </@f.history> @@ -20,7 +22,7 @@ <@f.overview> <p> - The <code>@FieldNameConstants</code> annotation generates an inner type which contains 1 constant for each field in your class; either string constants (fields marked <code>public static final</code>, of type <code>java.lang.String</code>) or if you prefer, an enum type with 1 value for each field - write <code>@FieldNameConstants(asEnum = true)</code> for the enum variant. <code>@FieldNameConstants</code> is useful for various marshalling and serialization frameworks. The constant field (whether enum value or string constant) always has the exact same name as the field, capitalization and all. + The <code>@FieldNameConstants</code> annotation generates an inner type which contains 1 constant for each field in your class; either string constants (fields marked <code>public static final</code>, of type <code>java.lang.String</code>) or if you prefer, an enum type with 1 value for each field - write <code>@FieldNameConstants(asEnum = true)</code> for the enum variant. <code>@FieldNameConstants</code> is useful for various marshalling and serialization frameworks. The constant field (whether enum value or string constant) always has the exact same name as the field, capitalization and all, unless you set the <code>lombok.fieldNameConstants.uppercase = true</code> option in your <code>lombok.config</code> file; in that case lombok will try to <code>UPPER_CASE</code> the name. </p><p> The generated inner type is by default called <code>Fields</code> and is <code>public</code>. You can modify this via <code>@FieldNameConstants(innerTypeName = "FieldNames", access = AccessLevel.PACKAGE)</code> for example. The default inner type name can also be modified via configuration key <code>lombok.fieldNameConstants.innerTypeName</code>. The generated fields are always <code>public</code>. </p><p> @@ -39,6 +41,10 @@ <code>lombok.fieldNameConstants.innerTypeName</code> = <em>a string</em> (default: 'Fields') </dt><dd> The name of the inner type generated by lombok can be controlled with this configuration key. + </dd><dt> + <code>lombok.fieldNameConstants.uppercase</code> = [<code>true</code> | <code>false</code>] (default: false) + </dt><dd> + If <code>true</code>, attempt to uppercase the generated fields. </dd> </@f.confKeys> |