Skip to content

Commit

Permalink
[issue #2092] Add an uppercase option to FieldNameConstants
Browse files Browse the repository at this point in the history
  • Loading branch information
rzwitserloot committed Apr 30, 2019
1 parent ac0eeac commit bf04992
Show file tree
Hide file tree
Showing 8 changed files with 80 additions and 11 deletions.
1 change: 1 addition & 0 deletions doc/changelog.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -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).
Expand Down
9 changes: 8 additions & 1 deletion src/core/lombok/ConfigurationKeys.java
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -543,6 +543,13 @@ private 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 -----

/**
Expand Down
12 changes: 8 additions & 4 deletions src/core/lombok/eclipse/handlers/HandleFieldNameConstants.java
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
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;
Expand All @@ -55,7 +56,7 @@

@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();

Expand All @@ -76,7 +77,7 @@ public void generateFieldNameConstantsForType(EclipseNode typeNode, EclipseNode
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);
}
}

Expand Down Expand Up @@ -112,11 +113,13 @@ private boolean fieldQualifiesForFieldNameConstantsGeneration(EclipseNode field,
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);
Expand Down Expand Up @@ -169,6 +172,7 @@ private void createInnerTypeFieldNameConstants(EclipseNode typeNode, EclipseNode
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;
Expand Down
14 changes: 9 additions & 5 deletions src/core/lombok/javac/handlers/HandleFieldNameConstants.java
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -30,6 +30,7 @@
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;
Expand All @@ -53,7 +54,7 @@

@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();

Expand All @@ -74,7 +75,7 @@ public void generateFieldNameConstantsForType(JavacNode typeNode, JavacNode erro
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);
}
}

Expand Down Expand Up @@ -117,11 +118,13 @@ public void handle(AnnotationValues<FieldNameConstants> annotation, JCAnnotation
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();
Expand Down Expand Up @@ -161,6 +164,7 @@ private void createInnerTypeFieldNameConstants(JavacNode typeNode, JavacNode err
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;
Expand Down
Original file line number Diff line number Diff line change
@@ -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";
}
}
Original file line number Diff line number Diff line change
@@ -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();
}
}
12 changes: 12 additions & 0 deletions test/transform/resource/before/FieldNameConstantsUppercased.java
Original file line number Diff line number Diff line change
@@ -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;
}
Original file line number Diff line number Diff line change
Expand Up @@ -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>

Expand All @@ -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>
Expand All @@ -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>

Expand Down

0 comments on commit bf04992

Please sign in to comment.