diff options
8 files changed, 138 insertions, 25 deletions
diff --git a/src/core/lombok/ConfigurationKeys.java b/src/core/lombok/ConfigurationKeys.java index 84b594f5..f70590f9 100644 --- a/src/core/lombok/ConfigurationKeys.java +++ b/src/core/lombok/ConfigurationKeys.java @@ -26,6 +26,7 @@ import java.util.List; import lombok.core.configuration.CallSuperType; import lombok.core.configuration.ConfigurationKey; import lombok.core.configuration.FlagUsageType; +import lombok.core.configuration.IdentifierName; import lombok.core.configuration.NullCheckExceptionType; import lombok.core.configuration.TypeName; @@ -416,7 +417,7 @@ public class ConfigurationKeys { * * If set the various log annotations (which make a log field) will use the stated identifier instead of {@code log} as a name. */ - public static final ConfigurationKey<String> LOG_ANY_FIELD_NAME = new ConfigurationKey<String>("lombok.log.fieldName", "Use this name for the generated logger fields (default: 'log').") {}; + public static final ConfigurationKey<IdentifierName> LOG_ANY_FIELD_NAME = new ConfigurationKey<IdentifierName>("lombok.log.fieldName", "Use this name for the generated logger fields (default: 'log').") {}; /** * lombok configuration: {@code lombok.log.fieldIsStatic} = {@code true} | {@code false}. @@ -541,7 +542,7 @@ public class ConfigurationKeys { * * The names of the constants generated by {@code @FieldNameConstants} will be prefixed with this value. */ - 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').") {}; + public static final ConfigurationKey<IdentifierName> FIELD_NAME_CONSTANTS_INNER_TYPE_NAME = new ConfigurationKey<IdentifierName>("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}. diff --git a/src/core/lombok/core/configuration/ConfigurationDataType.java b/src/core/lombok/core/configuration/ConfigurationDataType.java index 7512d2e6..40de65cf 100644 --- a/src/core/lombok/core/configuration/ConfigurationDataType.java +++ b/src/core/lombok/core/configuration/ConfigurationDataType.java @@ -110,6 +110,19 @@ public final class ConfigurationDataType { return "<fully.qualified.Type>"; } }); + map.put(IdentifierName.class, new ConfigurationValueParser() { + @Override public Object parse(String value) { + return IdentifierName.valueOf(value); + } + + @Override public String description() { + return "identifier-name"; + } + + @Override public String exampleValue() { + return "<javaIdentifier>"; + } + }); SIMPLE_TYPES = map; } diff --git a/src/core/lombok/core/configuration/IdentifierName.java b/src/core/lombok/core/configuration/IdentifierName.java new file mode 100644 index 00000000..fa8e03af --- /dev/null +++ b/src/core/lombok/core/configuration/IdentifierName.java @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2013 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 + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package lombok.core.configuration; + +import lombok.core.JavaIdentifiers; + +public final class IdentifierName { + private final String name; + + private IdentifierName(String name) { + this.name = name; + } + + public static IdentifierName valueOf(String name) { + if (name == null || name.trim().isEmpty()) { + return null; + } + String trimmedName = name.trim(); + if (!JavaIdentifiers.isValidJavaIdentifier(trimmedName)) { + throw new IllegalArgumentException("Invalid identifier " + trimmedName); + } + return new IdentifierName(trimmedName); + } + + @Override public boolean equals(Object obj) { + if (!(obj instanceof IdentifierName)) return false; + return name.equals(((IdentifierName) obj).name); + } + + @Override public int hashCode() { + return name.hashCode(); + } + + @Override public String toString() { + return name; + } + + public String getName() { + return name; + } +} diff --git a/src/core/lombok/core/configuration/TypeName.java b/src/core/lombok/core/configuration/TypeName.java index 989e1b97..8bcb2e5a 100644 --- a/src/core/lombok/core/configuration/TypeName.java +++ b/src/core/lombok/core/configuration/TypeName.java @@ -21,6 +21,8 @@ */ package lombok.core.configuration; +import lombok.core.JavaIdentifiers; + public final class TypeName { private final String name; @@ -29,7 +31,16 @@ public final class TypeName { } public static TypeName valueOf(String name) { - return new TypeName(name); + if (name == null || name.trim().isEmpty()) { + return null; + } + String trimmedName = name.trim(); + for (String identifier : trimmedName.split(".")) { + if (!JavaIdentifiers.isValidJavaIdentifier(identifier)) { + throw new IllegalArgumentException("Invalid type name " + trimmedName + " (part " + identifier + ")"); + } + } + return new TypeName(trimmedName); } @Override public boolean equals(Object obj) { @@ -44,4 +55,8 @@ public final class TypeName { @Override public String toString() { return name; } + + public String getName() { + return name; + } } diff --git a/src/core/lombok/eclipse/handlers/HandleFieldNameConstants.java b/src/core/lombok/eclipse/handlers/HandleFieldNameConstants.java index 574c1f41..710a26f8 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.configuration.IdentifierName; import lombok.core.handlers.HandlerUtil; import lombok.eclipse.Eclipse; import lombok.eclipse.EclipseAnnotationHandler; @@ -56,7 +57,9 @@ 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, boolean uppercase) { + private static final IdentifierName FIELDS = IdentifierName.valueOf("Fields"); + + public void generateFieldNameConstantsForType(EclipseNode typeNode, EclipseNode errorNode, AccessLevel level, boolean asEnum, IdentifierName innerTypeName, boolean onlyExplicit, boolean uppercase) { TypeDeclaration typeDecl = null; if (typeNode.get() instanceof TypeDeclaration) typeDecl = (TypeDeclaration) typeNode.get(); @@ -110,23 +113,29 @@ public class HandleFieldNameConstants extends EclipseAnnotationHandler<FieldName return; } - 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"; + IdentifierName innerTypeName; + try { + innerTypeName = IdentifierName.valueOf(annotationInstance.innerTypeName()); + } catch(IllegalArgumentException e) { + annotationNode.addError("InnerTypeName " + annotationInstance.innerTypeName() + " is not a valid Java identifier."); + return; + } + if (innerTypeName == null) innerTypeName = annotationNode.getAst().readConfiguration(ConfigurationKeys.FIELD_NAME_CONSTANTS_INNER_TYPE_NAME); + if (innerTypeName == null) 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(), uppercase); } - private void createInnerTypeFieldNameConstants(EclipseNode typeNode, EclipseNode errorNode, ASTNode source, AccessLevel level, List<EclipseNode> fields, boolean asEnum, String innerTypeName, boolean uppercase) { + private void createInnerTypeFieldNameConstants(EclipseNode typeNode, EclipseNode errorNode, ASTNode source, AccessLevel level, List<EclipseNode> fields, boolean asEnum, IdentifierName innerTypeName, boolean uppercase) { if (fields.isEmpty()) return; ASTVisitor generatedByVisitor = new SetGeneratedByVisitor(source); TypeDeclaration parent = (TypeDeclaration) typeNode.get(); - EclipseNode fieldsType = findInnerClass(typeNode, innerTypeName); + EclipseNode fieldsType = findInnerClass(typeNode, innerTypeName.getName()); boolean genConstr = false, genClinit = false; - char[] name = innerTypeName.toCharArray(); + char[] name = innerTypeName.getName().toCharArray(); TypeDeclaration generatedInnerType = null; if (fieldsType == null) { generatedInnerType = new TypeDeclaration(parent.compilationResult); diff --git a/src/core/lombok/eclipse/handlers/HandleLog.java b/src/core/lombok/eclipse/handlers/HandleLog.java index 8c7f7971..62ad8fab 100644 --- a/src/core/lombok/eclipse/handlers/HandleLog.java +++ b/src/core/lombok/eclipse/handlers/HandleLog.java @@ -30,6 +30,7 @@ import java.util.Arrays; import lombok.ConfigurationKeys; import lombok.core.AnnotationValues; +import lombok.core.configuration.IdentifierName; import lombok.eclipse.EclipseAnnotationHandler; import lombok.eclipse.EclipseNode; import lombok.eclipse.handlers.EclipseHandlerUtil.MemberExistsResult; @@ -48,6 +49,8 @@ import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; import org.mangosdk.spi.ProviderFor; public class HandleLog { + private static final IdentifierName LOG = IdentifierName.valueOf("log"); + private HandleLog() { throw new UnsupportedOperationException(); } @@ -57,8 +60,8 @@ public class HandleLog { switch (owner.getKind()) { case TYPE: - String logFieldName = annotationNode.getAst().readConfiguration(ConfigurationKeys.LOG_ANY_FIELD_NAME); - if (logFieldName == null) logFieldName = "log"; + IdentifierName logFieldName = annotationNode.getAst().readConfiguration(ConfigurationKeys.LOG_ANY_FIELD_NAME); + if (logFieldName == null) logFieldName = LOG; boolean useStatic = !Boolean.FALSE.equals(annotationNode.getAst().readConfiguration(ConfigurationKeys.LOG_ANY_FIELD_IS_STATIC)); @@ -74,14 +77,14 @@ public class HandleLog { return; } - if (fieldExists(logFieldName, owner) != MemberExistsResult.NOT_EXISTS) { + if (fieldExists(logFieldName.getName(), owner) != MemberExistsResult.NOT_EXISTS) { annotationNode.addWarning("Field '" + logFieldName + "' already exists."); return; } ClassLiteralAccess loggingType = selfType(owner, source); - FieldDeclaration fieldDeclaration = createField(framework, source, loggingType, logFieldName, useStatic, loggerTopic); + FieldDeclaration fieldDeclaration = createField(framework, source, loggingType, logFieldName.getName(), useStatic, loggerTopic); fieldDeclaration.traverse(new SetGeneratedByVisitor(source), typeDecl.staticInitializerScope); // TODO temporary workaround for issue 217. http://code.google.com/p/projectlombok/issues/detail?id=217 // injectFieldSuppressWarnings(owner, fieldDeclaration); diff --git a/src/core/lombok/javac/handlers/HandleFieldNameConstants.java b/src/core/lombok/javac/handlers/HandleFieldNameConstants.java index 628e83dc..ec4015c7 100644 --- a/src/core/lombok/javac/handlers/HandleFieldNameConstants.java +++ b/src/core/lombok/javac/handlers/HandleFieldNameConstants.java @@ -30,6 +30,7 @@ import lombok.AccessLevel; import lombok.ConfigurationKeys; import lombok.core.AST.Kind; import lombok.core.AnnotationValues; +import lombok.core.configuration.IdentifierName; import lombok.core.handlers.HandlerUtil; import lombok.experimental.FieldNameConstants; import lombok.javac.JavacAnnotationHandler; @@ -54,7 +55,9 @@ 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, boolean uppercase) { + private static final IdentifierName FIELDS = IdentifierName.valueOf("Fields"); + + public void generateFieldNameConstantsForType(JavacNode typeNode, JavacNode errorNode, AccessLevel level, boolean asEnum, IdentifierName innerTypeName, boolean onlyExplicit, boolean uppercase) { JCClassDecl typeDecl = null; if (typeNode.get() instanceof JCClassDecl) typeDecl = (JCClassDecl) typeNode.get(); @@ -115,24 +118,30 @@ public class HandleFieldNameConstants extends JavacAnnotationHandler<FieldNameCo return; } - 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"; + IdentifierName innerTypeName; + try { + innerTypeName = IdentifierName.valueOf(annotationInstance.innerTypeName()); + } catch(IllegalArgumentException e) { + annotationNode.addError("InnerTypeName " + annotationInstance.innerTypeName() + " is not a valid Java identifier."); + return; + } + if (innerTypeName == null) innerTypeName = annotationNode.getAst().readConfiguration(ConfigurationKeys.FIELD_NAME_CONSTANTS_INNER_TYPE_NAME); + if (innerTypeName == null) 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(), uppercase); } - private void createInnerTypeFieldNameConstants(JavacNode typeNode, JavacNode errorNode, JCTree pos, AccessLevel level, java.util.List<JavacNode> fields, boolean asEnum, String innerTypeName, boolean uppercase) { + private void createInnerTypeFieldNameConstants(JavacNode typeNode, JavacNode errorNode, JCTree pos, AccessLevel level, java.util.List<JavacNode> fields, boolean asEnum, IdentifierName innerTypeName, boolean uppercase) { if (fields.isEmpty()) return; JavacTreeMaker maker = typeNode.getTreeMaker(); JCModifiers mods = maker.Modifiers(toJavacModifier(level) | (asEnum ? Flags.ENUM : Flags.STATIC | Flags.FINAL)); - Name fieldsName = typeNode.toName(innerTypeName); + Name fieldsName = typeNode.toName(innerTypeName.getName()); - JavacNode fieldsType = findInnerClass(typeNode, innerTypeName); + JavacNode fieldsType = findInnerClass(typeNode, innerTypeName.getName()); boolean genConstr = false; if (fieldsType == null) { JCClassDecl innerType = maker.ClassDef(mods, fieldsName, List.<JCTypeParameter>nil(), null, List.<JCExpression>nil(), List.<JCTree>nil()); diff --git a/src/core/lombok/javac/handlers/HandleLog.java b/src/core/lombok/javac/handlers/HandleLog.java index 6d742e76..da180cec 100644 --- a/src/core/lombok/javac/handlers/HandleLog.java +++ b/src/core/lombok/javac/handlers/HandleLog.java @@ -28,6 +28,7 @@ import java.lang.annotation.Annotation; import lombok.ConfigurationKeys; import lombok.core.AnnotationValues; +import lombok.core.configuration.IdentifierName; import lombok.javac.JavacAnnotationHandler; import lombok.javac.JavacNode; import lombok.javac.JavacTreeMaker; @@ -46,6 +47,8 @@ import com.sun.tools.javac.util.List; import com.sun.tools.javac.util.Name; public class HandleLog { + private static final IdentifierName LOG = IdentifierName.valueOf("log"); + private HandleLog() { throw new UnsupportedOperationException(); } @@ -56,8 +59,8 @@ public class HandleLog { JavacNode typeNode = annotationNode.up(); switch (typeNode.getKind()) { case TYPE: - String logFieldName = annotationNode.getAst().readConfiguration(ConfigurationKeys.LOG_ANY_FIELD_NAME); - if (logFieldName == null) logFieldName = "log"; + IdentifierName logFieldName = annotationNode.getAst().readConfiguration(ConfigurationKeys.LOG_ANY_FIELD_NAME); + if (logFieldName == null) logFieldName = LOG; boolean useStatic = !Boolean.FALSE.equals(annotationNode.getAst().readConfiguration(ConfigurationKeys.LOG_ANY_FIELD_IS_STATIC)); @@ -65,13 +68,13 @@ public class HandleLog { annotationNode.addError("@Log is legal only on classes and enums."); return; } - if (fieldExists(logFieldName, typeNode) != MemberExistsResult.NOT_EXISTS) { + if (fieldExists(logFieldName.getName(), typeNode) != MemberExistsResult.NOT_EXISTS) { annotationNode.addWarning("Field '" + logFieldName + "' already exists."); return; } JCFieldAccess loggingType = selfType(typeNode); - createField(framework, typeNode, loggingType, annotationNode.get(), logFieldName, useStatic, loggerTopic); + createField(framework, typeNode, loggingType, annotationNode.get(), logFieldName.getName(), useStatic, loggerTopic); break; default: annotationNode.addError("@Log is legal only on types."); |