diff options
Diffstat (limited to 'src/core/lombok')
-rw-r--r-- | src/core/lombok/core/handlers/TransformationsUtil.java | 91 | ||||
-rw-r--r-- | src/core/lombok/eclipse/handlers/HandleSetter.java | 31 | ||||
-rw-r--r-- | src/core/lombok/javac/handlers/HandleSetter.java | 27 | ||||
-rw-r--r-- | src/core/lombok/javac/handlers/JavacHandlerUtil.java | 16 |
4 files changed, 112 insertions, 53 deletions
diff --git a/src/core/lombok/core/handlers/TransformationsUtil.java b/src/core/lombok/core/handlers/TransformationsUtil.java index 7f6faf99..50c1ca02 100644 --- a/src/core/lombok/core/handlers/TransformationsUtil.java +++ b/src/core/lombok/core/handlers/TransformationsUtil.java @@ -22,7 +22,6 @@ package lombok.core.handlers; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collections; import java.util.HashSet; import java.util.List; @@ -38,10 +37,6 @@ 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. * @@ -54,7 +49,7 @@ 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 + * Note that for boolean fields, if the field starts with '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. * @@ -66,15 +61,9 @@ 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(); - } + if (isBoolean && fieldName.toString().startsWith("is") && fieldName.length() > 2 && !Character.isLowerCase(fieldName.charAt(2))) { + // The field is for example named 'isRunning'. + return fieldName.toString(); } return buildName(prefix, fieldName.toString()); @@ -87,7 +76,7 @@ public class TransformationsUtil { public static final Pattern NULLABLE_PATTERN = Pattern.compile("^(?:nullable|checkfornull)$", Pattern.CASE_INSENSITIVE); /** - * Generates a getter name from a given field name. + * Generates a setter name from a given field name. * * Strategy: * @@ -96,9 +85,19 @@ public class TransformationsUtil { * * return "set" plus the possibly title/uppercased first character, and the rest of the field name. * + * Note that if the field is boolean and starts with 'is' followed by a non-lowercase letter, the 'is' is stripped and replaced with 'set'. + * * @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}. */ - public static String toSetterName(CharSequence fieldName) { + public static String toSetterName(CharSequence fieldName, boolean isBoolean) { + if (fieldName.length() == 0) return "set"; + + if (isBoolean && fieldName.toString().startsWith("is") && fieldName.length() > 2 && !Character.isLowerCase(fieldName.charAt(2))) { + // The field is for example named 'isRunning'. + return "set" + fieldName.toString().substring(2); + } + return buildName("set", fieldName.toString()); } @@ -116,21 +115,24 @@ public class TransformationsUtil { return String.format("%s%s", prefix, suffix); } + /** + * Returns all names of methods that would represent the getter for a field with the provided name. + * + * For example if {@code isBoolean} is true, then a field named {@code isRunning} would produce:<br /> + * {@code [isRunning, getRunning, isIsRunning, getIsRunning]} + * + * @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}. + */ 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. - } + + // isPrefix = field is called something like 'isRunning', so 'running' could also be the fieldname. + if (fieldName.toString().startsWith("is") && fieldName.length() > 2 && !Character.isLowerCase(fieldName.charAt(2))) { + baseNames.add(fieldName.toString().substring(2)); } Set<String> names = new HashSet<String>(); @@ -139,9 +141,40 @@ public class TransformationsUtil { baseName = Character.toTitleCase(baseName.charAt(0)) + baseName.substring(1); } - for (String prefix : KNOWN_BOOLEAN_PREFIXES) { - names.add(prefix + baseName); + names.add("is" + baseName); + names.add("get" + baseName); + } + + return new ArrayList<String>(names); + } + + /** + * Returns all names of methods that would represent the setter for a field with the provided name. + * + * For example if {@code isBoolean} is true, then a field named {@code isRunning} would produce:<br /> + * {@code [setRunning, setIsRunning]} + * + * @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}. + */ + public static List<String> toAllSetterNames(CharSequence fieldName, boolean isBoolean) { + if (!isBoolean) return Collections.singletonList(toSetterName(fieldName, false)); + + List<String> baseNames = new ArrayList<String>(); + baseNames.add(fieldName.toString()); + + // isPrefix = field is called something like 'isRunning', so 'running' could also be the fieldname. + if (fieldName.toString().startsWith("is") && fieldName.length() > 2 && !Character.isLowerCase(fieldName.charAt(2))) { + baseNames.add(fieldName.toString().substring(2)); + } + + 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); } + + names.add("set" + baseName); } return new ArrayList<String>(names); diff --git a/src/core/lombok/eclipse/handlers/HandleSetter.java b/src/core/lombok/eclipse/handlers/HandleSetter.java index 14ff0e10..945495c6 100644 --- a/src/core/lombok/eclipse/handlers/HandleSetter.java +++ b/src/core/lombok/eclipse/handlers/HandleSetter.java @@ -157,21 +157,28 @@ public class HandleSetter implements EclipseAnnotationHandler<Setter> { } FieldDeclaration field = (FieldDeclaration) fieldNode.get(); - String setterName = TransformationsUtil.toSetterName(new String(field.name)); + TypeReference fieldType = copyType(field.type, source); + boolean isBoolean = nameEquals(fieldType.getTypeName(), "boolean") && fieldType.dimensions() == 0; + String setterName = TransformationsUtil.toSetterName(new String(field.name), isBoolean); int modifier = toEclipseModifier(level) | (field.modifiers & ClassFileConstants.AccStatic); - switch (methodExists(setterName, fieldNode, false)) { - case EXISTS_BY_LOMBOK: - return true; - case EXISTS_BY_USER: - if (whineIfExists) errorNode.addWarning( - String.format("Not generating %s(%s %s): A method with that name already exists", - setterName, field.type, new String(field.name))); - return true; - default: - case NOT_EXISTS: - //continue with creating the setter + for (String altName : TransformationsUtil.toAllSetterNames(new String(field.name), isBoolean)) { + switch (methodExists(altName, fieldNode, false)) { + case EXISTS_BY_LOMBOK: + return true; + case EXISTS_BY_USER: + if (whineIfExists) { + String altNameExpl = ""; + if (!altName.equals(setterName)) altNameExpl = String.format(" (%s)", altName); + errorNode.addWarning( + String.format("Not generating %s(): A method with that name already exists%s", setterName, altNameExpl)); + } + return true; + default: + case NOT_EXISTS: + //continue scanning the other alt names. + } } MethodDeclaration method = generateSetter((TypeDeclaration) fieldNode.up().get(), fieldNode, setterName, modifier, source, onParam); diff --git a/src/core/lombok/javac/handlers/HandleSetter.java b/src/core/lombok/javac/handlers/HandleSetter.java index 6dd88abd..ec5195ac 100644 --- a/src/core/lombok/javac/handlers/HandleSetter.java +++ b/src/core/lombok/javac/handlers/HandleSetter.java @@ -174,17 +174,22 @@ public class HandleSetter implements JavacAnnotationHandler<Setter> { JCVariableDecl fieldDecl = (JCVariableDecl)fieldNode.get(); String methodName = toSetterName(fieldDecl); - switch (methodExists(methodName, fieldNode, false)) { - case EXISTS_BY_LOMBOK: - return true; - case EXISTS_BY_USER: - if (whineIfExists) errorNode.addWarning( - String.format("Not generating %s(%s %s): A method with that name already exists", - methodName, fieldDecl.vartype, fieldDecl.name)); - return true; - default: - case NOT_EXISTS: - //continue with creating the setter + for (String altName : toAllSetterNames(fieldDecl)) { + switch (methodExists(altName, fieldNode, false)) { + 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/core/lombok/javac/handlers/JavacHandlerUtil.java b/src/core/lombok/javac/handlers/JavacHandlerUtil.java index aa4e1bb2..1fb72dfa 100644 --- a/src/core/lombok/javac/handlers/JavacHandlerUtil.java +++ b/src/core/lombok/javac/handlers/JavacHandlerUtil.java @@ -159,6 +159,18 @@ public class JavacHandlerUtil { } /** + * Translates the given field into all possible setter names. + * Convenient wrapper around {@link TransformationsUtil#toAllSetterNames(CharSequence, boolean)}. + */ + public static java.util.List<String> toAllSetterNames(JCVariableDecl field) { + CharSequence fieldName = field.name; + + boolean isBoolean = field.vartype.toString().equals("boolean"); + + return TransformationsUtil.toAllSetterNames(fieldName, isBoolean); + } + + /** * @return the likely setter name for the stated field. (e.g. private boolean foo; to setFoo). * * Convenient wrapper around {@link TransformationsUtil#toSetterName(CharSequence)}. @@ -166,7 +178,9 @@ public class JavacHandlerUtil { public static String toSetterName(JCVariableDecl field) { CharSequence fieldName = field.name; - return TransformationsUtil.toSetterName(fieldName); + boolean isBoolean = field.vartype.toString().equals("boolean"); + + return TransformationsUtil.toSetterName(fieldName, isBoolean); } /** Serves as return value for the methods that check for the existence of fields and methods. */ |