diff options
-rw-r--r-- | src/lombok/core/TransformationsUtil.java | 57 | ||||
-rw-r--r-- | src/lombok/eclipse/handlers/HandleGetter.java | 31 | ||||
-rw-r--r-- | src/lombok/javac/handlers/HandleGetter.java | 26 | ||||
-rw-r--r-- | src/lombok/javac/handlers/PKG.java | 8 |
4 files changed, 100 insertions, 22 deletions
diff --git a/src/lombok/core/TransformationsUtil.java b/src/lombok/core/TransformationsUtil.java index bc30fecc..12b90d0e 100644 --- a/src/lombok/core/TransformationsUtil.java +++ b/src/lombok/core/TransformationsUtil.java @@ -21,6 +21,13 @@ */ package lombok.core; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + /** * Container for static utility methods useful for some of the standard lombok transformations, regardless of * target platform (e.g. useful for both javac and Eclipse lombok implementations). @@ -30,6 +37,10 @@ public class TransformationsUtil { //Prevent instantiation } + private static final List<String> KNOWN_BOOLEAN_PREFIXES = Collections.unmodifiableList(Arrays.asList( + "is", "has", "get" + )); + /** * Generates a getter name from a given field name. * @@ -42,6 +53,10 @@ public class TransformationsUtil { * * return the prefix plus the possibly title/uppercased first character, and the rest of the field name. * + * Note that for boolean fields, if the field starts with 'has', 'get', or 'is', and the character after that is + * <b>not</b> a lowercase character, the field name is returned without changing any character's case and without + * any prefix. + * * @param fieldName the name of the field. * @param isBoolean if the field is of type 'boolean'. For fields of type 'java.lang.Boolean', you should provide <code>false</code>. */ @@ -50,6 +65,17 @@ public class TransformationsUtil { if ( fieldName.length() == 0 ) return prefix; + for ( String knownBooleanPrefix : KNOWN_BOOLEAN_PREFIXES ) { + if ( !fieldName.toString().startsWith(knownBooleanPrefix) ) continue; + if ( fieldName.length() > knownBooleanPrefix.length() && + !Character.isLowerCase(fieldName.charAt(knownBooleanPrefix.length())) ) { + //The field is called something like 'isFoo' or 'hasFoo' or 'getFoo', so we shouldn't + //prefix with 'is' but instead just use the field name as is. The isLowerCase check is so we don't turn + //hashCodeGenerated, which so happens to start with 'has', into hasHCodeGenerated instead of isHashCodeGenerated. + return fieldName.toString(); + } + } + return buildName(prefix, fieldName.toString()); } @@ -82,4 +108,35 @@ public class TransformationsUtil { } return String.format("%s%s", prefix, suffix); } + + public static List<String> toAllGetterNames(CharSequence fieldName, boolean isBoolean) { + if ( !isBoolean ) return Collections.singletonList(toGetterName(fieldName, false)); + + List<String> baseNames = new ArrayList<String>(); + baseNames.add(fieldName.toString()); + for ( String knownBooleanPrefix : KNOWN_BOOLEAN_PREFIXES ) { + if ( !fieldName.toString().startsWith(knownBooleanPrefix) ) continue; + if ( fieldName.length() > knownBooleanPrefix.length() && + !Character.isLowerCase(fieldName.charAt(knownBooleanPrefix.length())) ) { + //The field is called something like 'isFoo' or 'hasFoo' or 'getFoo', so the practical fieldname + //could also be 'foo'. + baseNames.add(fieldName.toString().substring(knownBooleanPrefix.length())); + //prefix with 'is' but instead just use the field name as is. The isLowerCase check is so we don't turn + //hashCodeGenerated, which so happens to start with 'has', into hasHCodeGenerated instead of isHashCodeGenerated. + } + } + + Set<String> names = new HashSet<String>(); + for ( String baseName : baseNames ) { + if ( baseName.length() > 0 && Character.isLowerCase(baseName.charAt(0)) ) { + baseName = Character.toTitleCase(baseName.charAt(0)) + baseName.substring(1); + } + + for ( String prefix : KNOWN_BOOLEAN_PREFIXES ) { + names.add(prefix + baseName); + } + } + + return new ArrayList<String>(names); + } } diff --git a/src/lombok/eclipse/handlers/HandleGetter.java b/src/lombok/eclipse/handlers/HandleGetter.java index 0bdde361..efb37c35 100644 --- a/src/lombok/eclipse/handlers/HandleGetter.java +++ b/src/lombok/eclipse/handlers/HandleGetter.java @@ -88,21 +88,28 @@ public class HandleGetter implements EclipseAnnotationHandler<Getter> { FieldDeclaration field = (FieldDeclaration) fieldNode.get(); TypeReference fieldType = Eclipse.copyType(field.type); - String getterName = TransformationsUtil.toGetterName( - new String(field.name), nameEquals(fieldType.getTypeName(), "boolean") && fieldType.dimensions() == 0); + String fieldName = new String(field.name); + boolean isBoolean = nameEquals(fieldType.getTypeName(), "boolean") && fieldType.dimensions() == 0; + String getterName = TransformationsUtil.toGetterName(fieldName, isBoolean); int modifier = toModifier(level) | (field.modifiers & ClassFileConstants.AccStatic); - switch ( methodExists(getterName, fieldNode) ) { - case EXISTS_BY_LOMBOK: - return true; - case EXISTS_BY_USER: - if ( whineIfExists ) errorNode.addWarning( - String.format("Not generating %s(): A method with that name already exists", getterName)); - return true; - default: - case NOT_EXISTS: - //continue with creating the getter + for ( String altName : TransformationsUtil.toAllGetterNames(fieldName, isBoolean) ) { + switch ( methodExists(altName, fieldNode) ) { + case EXISTS_BY_LOMBOK: + return true; + case EXISTS_BY_USER: + if ( whineIfExists ) { + String altNameExpl = ""; + if ( !altName.equals(getterName) ) altNameExpl = String.format("(%s)", altName); + errorNode.addWarning( + String.format("Not generating %s(): A method with that name already exists%s", getterName, altNameExpl)); + } + return true; + default: + case NOT_EXISTS: + //continue scanning the other alt names. + } } MethodDeclaration method = generateGetter((TypeDeclaration) fieldNode.up().get(), field, getterName, modifier, pos); diff --git a/src/lombok/javac/handlers/HandleGetter.java b/src/lombok/javac/handlers/HandleGetter.java index c993afcd..81915169 100644 --- a/src/lombok/javac/handlers/HandleGetter.java +++ b/src/lombok/javac/handlers/HandleGetter.java @@ -90,16 +90,22 @@ public class HandleGetter implements JavacAnnotationHandler<Getter> { JCVariableDecl fieldDecl = (JCVariableDecl)fieldNode.get(); String methodName = toGetterName(fieldDecl); - switch ( methodExists(methodName, fieldNode) ) { - case EXISTS_BY_LOMBOK: - return true; - case EXISTS_BY_USER: - if ( whineIfExists ) errorNode.addWarning( - String.format("Not generating %s(): A method with that name already exists", methodName)); - return true; - default: - case NOT_EXISTS: - //continue with creating the getter + for ( String altName : toAllGetterNames(fieldDecl) ) { + switch ( methodExists(altName, fieldNode) ) { + case EXISTS_BY_LOMBOK: + return true; + case EXISTS_BY_USER: + if ( whineIfExists ) { + String altNameExpl = ""; + if ( !altName.equals(methodName) ) altNameExpl = String.format("(%s)", altName); + errorNode.addWarning( + String.format("Not generating %s(): A method with that name already exists%s", methodName, altNameExpl)); + } + return true; + default: + case NOT_EXISTS: + //continue scanning the other alt names. + } } long access = toJavacModifier(level) | (fieldDecl.mods.flags & Flags.STATIC); diff --git a/src/lombok/javac/handlers/PKG.java b/src/lombok/javac/handlers/PKG.java index ef6b3eba..205a2b6e 100644 --- a/src/lombok/javac/handlers/PKG.java +++ b/src/lombok/javac/handlers/PKG.java @@ -45,6 +45,14 @@ class PKG { //Prevent instantiation } + static java.util.List<String> toAllGetterNames(JCVariableDecl field) { + CharSequence fieldName = field.name; + + boolean isBoolean = field.vartype.toString().equals("boolean"); + + return TransformationsUtil.toAllGetterNames(fieldName, isBoolean); + } + /** * @return the likely getter name for the stated field. (e.g. private boolean foo; to isFoo). */ |