aboutsummaryrefslogtreecommitdiff
path: root/src/core/lombok
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/lombok')
-rw-r--r--src/core/lombok/Cleanup.java2
-rw-r--r--src/core/lombok/ConfigurationKeys.java350
-rw-r--r--src/core/lombok/Delegate.java2
-rw-r--r--src/core/lombok/EqualsAndHashCode.java2
-rw-r--r--src/core/lombok/NonNull.java3
-rw-r--r--src/core/lombok/SneakyThrows.java2
-rw-r--r--src/core/lombok/Synchronized.java2
-rw-r--r--src/core/lombok/ToString.java2
-rw-r--r--src/core/lombok/core/AST.java14
-rw-r--r--src/core/lombok/core/FlagUsageType.java6
-rw-r--r--src/core/lombok/core/LombokConfiguration.java54
-rw-r--r--src/core/lombok/core/TransformationsUtil.java306
-rw-r--r--src/core/lombok/core/configuration/BubblingConfigurationResolver.java78
-rw-r--r--src/core/lombok/core/configuration/ConfigurationApp.java376
-rw-r--r--src/core/lombok/core/configuration/ConfigurationDataType.java182
-rw-r--r--src/core/lombok/core/configuration/ConfigurationKey.java96
-rw-r--r--src/core/lombok/core/configuration/ConfigurationKeysLoader.java57
-rw-r--r--src/core/lombok/core/configuration/ConfigurationParser.java109
-rw-r--r--src/core/lombok/core/configuration/ConfigurationProblemReporter.java32
-rw-r--r--src/core/lombok/core/configuration/ConfigurationResolver.java26
-rw-r--r--src/core/lombok/core/configuration/ConfigurationResolverFactory.java28
-rw-r--r--src/core/lombok/core/configuration/ConfigurationSource.java67
-rw-r--r--src/core/lombok/core/configuration/ConfigurationValueParser.java28
-rw-r--r--src/core/lombok/core/configuration/FileSystemSourceCache.java184
-rw-r--r--src/core/lombok/core/configuration/StringConfigurationSource.java90
-rw-r--r--src/core/lombok/core/configuration/TypeName.java47
-rw-r--r--src/core/lombok/core/handlers/HandlerUtil.java361
-rw-r--r--src/core/lombok/eclipse/EclipseAST.java27
-rw-r--r--src/core/lombok/eclipse/HandlerLibrary.java5
-rw-r--r--src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java36
-rw-r--r--src/core/lombok/eclipse/handlers/HandleAccessors.java43
-rw-r--r--src/core/lombok/eclipse/handlers/HandleBuilder.java6
-rw-r--r--src/core/lombok/eclipse/handlers/HandleCleanup.java4
-rw-r--r--src/core/lombok/eclipse/handlers/HandleConstructor.java17
-rw-r--r--src/core/lombok/eclipse/handlers/HandleData.java9
-rw-r--r--src/core/lombok/eclipse/handlers/HandleEqualsAndHashCode.java7
-rw-r--r--src/core/lombok/eclipse/handlers/HandleExtensionMethod.java7
-rw-r--r--src/core/lombok/eclipse/handlers/HandleFieldDefaults.java6
-rw-r--r--src/core/lombok/eclipse/handlers/HandleGetter.java9
-rw-r--r--src/core/lombok/eclipse/handlers/HandleLog.java36
-rw-r--r--src/core/lombok/eclipse/handlers/HandleNonNull.java4
-rw-r--r--src/core/lombok/eclipse/handlers/HandlePrintAST.java17
-rw-r--r--src/core/lombok/eclipse/handlers/HandleSetter.java9
-rw-r--r--src/core/lombok/eclipse/handlers/HandleSneakyThrows.java4
-rw-r--r--src/core/lombok/eclipse/handlers/HandleSynchronized.java4
-rw-r--r--src/core/lombok/eclipse/handlers/HandleToString.java19
-rw-r--r--src/core/lombok/eclipse/handlers/HandleVal.java6
-rw-r--r--src/core/lombok/eclipse/handlers/HandleValue.java6
-rw-r--r--src/core/lombok/eclipse/handlers/HandleWither.java11
-rw-r--r--src/core/lombok/experimental/Accessors.java2
-rw-r--r--src/core/lombok/experimental/ExtensionMethod.java2
-rw-r--r--src/core/lombok/experimental/FieldDefaults.java2
-rw-r--r--src/core/lombok/extern/apachecommons/CommonsLog.java2
-rw-r--r--src/core/lombok/extern/java/Log.java2
-rw-r--r--src/core/lombok/extern/log4j/Log4j.java2
-rw-r--r--src/core/lombok/extern/log4j/Log4j2.java2
-rw-r--r--src/core/lombok/extern/slf4j/Slf4j.java2
-rw-r--r--src/core/lombok/extern/slf4j/XSlf4j.java1
-rw-r--r--src/core/lombok/javac/HandlerLibrary.java2
-rw-r--r--src/core/lombok/javac/JavacAST.java14
-rw-r--r--src/core/lombok/javac/handlers/HandleAccessors.java7
-rw-r--r--src/core/lombok/javac/handlers/HandleBuilder.java6
-rw-r--r--src/core/lombok/javac/handlers/HandleCleanup.java4
-rw-r--r--src/core/lombok/javac/handlers/HandleConstructor.java19
-rw-r--r--src/core/lombok/javac/handlers/HandleData.java6
-rw-r--r--src/core/lombok/javac/handlers/HandleDelegate.java4
-rw-r--r--src/core/lombok/javac/handlers/HandleEqualsAndHashCode.java4
-rw-r--r--src/core/lombok/javac/handlers/HandleExtensionMethod.java6
-rw-r--r--src/core/lombok/javac/handlers/HandleFieldDefaults.java6
-rw-r--r--src/core/lombok/javac/handlers/HandleGetter.java9
-rw-r--r--src/core/lombok/javac/handlers/HandleLog.java34
-rw-r--r--src/core/lombok/javac/handlers/HandleNonNull.java4
-rw-r--r--src/core/lombok/javac/handlers/HandlePrintAST.java14
-rw-r--r--src/core/lombok/javac/handlers/HandleSetter.java9
-rw-r--r--src/core/lombok/javac/handlers/HandleSneakyThrows.java4
-rw-r--r--src/core/lombok/javac/handlers/HandleSynchronized.java6
-rw-r--r--src/core/lombok/javac/handlers/HandleToString.java16
-rw-r--r--src/core/lombok/javac/handlers/HandleVal.java7
-rw-r--r--src/core/lombok/javac/handlers/HandleValue.java7
-rw-r--r--src/core/lombok/javac/handlers/HandleWither.java9
-rw-r--r--src/core/lombok/javac/handlers/JavacHandlerUtil.java62
-rw-r--r--src/core/lombok/val.java5
82 files changed, 2628 insertions, 451 deletions
diff --git a/src/core/lombok/Cleanup.java b/src/core/lombok/Cleanup.java
index eb223958..4b5c6fc2 100644
--- a/src/core/lombok/Cleanup.java
+++ b/src/core/lombok/Cleanup.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009 The Project Lombok Authors.
+ * Copyright (C) 2009-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
diff --git a/src/core/lombok/ConfigurationKeys.java b/src/core/lombok/ConfigurationKeys.java
new file mode 100644
index 00000000..9d9d17b4
--- /dev/null
+++ b/src/core/lombok/ConfigurationKeys.java
@@ -0,0 +1,350 @@
+/*
+ * Copyright (C) 2013-2014 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;
+
+import java.util.List;
+
+import lombok.core.FlagUsageType;
+import lombok.core.configuration.ConfigurationKey;
+
+/**
+ * A container class containing all lombok configuration keys that do not belong to a specific annotation.
+ */
+public class ConfigurationKeys {
+ private ConfigurationKeys() {}
+
+ // ##### main package features #####
+
+ // ----- *ArgsConstructor -----
+
+ /**
+ * lombok configuration: {@code lombok.AnyConstructor.flagUsage} = {@code WARNING} | {@code ERROR}.
+ *
+ * If set, <em>any</em> usage of {@code @AllArgsConstructor}, {@code @RequiredArgsConstructor}, or {@code @NoArgsConstructor} results in a warning / error.
+ */
+ public static final ConfigurationKey<FlagUsageType> ANY_CONSTRUCTOR_FLAG_USAGE = new ConfigurationKey<FlagUsageType>("lombok.AnyConstructor.flagUsage", "Emit a warning or error if any of the XxxArgsConstructor annotations are used.") {};
+
+ /**
+ * lombok configuration: {@code lombok.AllArgsConstructor.flagUsage} = {@code WARNING} | {@code ERROR}.
+ *
+ * If set, <em>any</em> usage of {@code @AllArgsConstructor} results in a warning / error.
+ */
+ public static final ConfigurationKey<FlagUsageType> ALL_ARGS_CONSTRUCTOR_FLAG_USAGE = new ConfigurationKey<FlagUsageType>("lombok.AllArgsConstructor.flagUsage", "Emit a warning or error if @AllArgsConstructor is used.") {};
+
+ /**
+ * lombok configuration: {@code lombok.NoArgsConstructor.flagUsage} = {@code WARNING} | {@code ERROR}.
+ *
+ * If set, <em>any</em> usage of {@code @NoArgsConstructor} results in a warning / error.
+ */
+ public static final ConfigurationKey<FlagUsageType> NO_ARGS_CONSTRUCTOR_FLAG_USAGE = new ConfigurationKey<FlagUsageType>("lombok.NoArgsConstructor.flagUsage", "Emit a warning or error if @NoArgsConstructor is used.") {};
+
+ /**
+ * lombok configuration: {@code lombok.RequiredArgsConstructor.flagUsage} = {@code WARNING} | {@code ERROR}.
+ *
+ * If set, <em>any</em> usage of {@code @RequiredArgsConstructor} results in a warning / error.
+ */
+ public static final ConfigurationKey<FlagUsageType> REQUIRED_ARGS_CONSTRUCTOR_FLAG_USAGE = new ConfigurationKey<FlagUsageType>("lombok.RequiredArgsConstructor.flagUsage", "Emit a warning or error if @RequiredArgsConstructor is used.") {};
+
+ // ##### Beanies #####
+
+ // ----- Data -----
+
+ /**
+ * lombok configuration: {@code lombok.Data.flagUsage} = {@code WARNING} | {@code ERROR}.
+ *
+ * If set, <em>any</em> usage of {@code @Data} results in a warning / error.
+ */
+ public static final ConfigurationKey<FlagUsageType> DATA_FLAG_USAGE = new ConfigurationKey<FlagUsageType>("lombok.Data.flagUsage", "Emit a warning or error if @Data is used.") {};
+
+ // ----- Value -----
+
+ /**
+ * lombok configuration: {@code lombok.Value.flagUsage} = {@code WARNING} | {@code ERROR}.
+ *
+ * If set, <em>any</em> usage of {@code @Value} results in a warning / error.
+ */
+ public static final ConfigurationKey<FlagUsageType> VALUE_FLAG_USAGE = new ConfigurationKey<FlagUsageType>("lombok.Value.flagUsage", "Emit a warning or error if @Value is used.") {};
+
+ // ----- Getter -----
+
+ /**
+ * lombok configuration: {@code lombok.Getter.flagUsage} = {@code WARNING} | {@code ERROR}.
+ *
+ * If set, <em>any</em> usage of {@code @Getter} results in a warning / error.
+ */
+ public static final ConfigurationKey<FlagUsageType> GETTER_FLAG_USAGE = new ConfigurationKey<FlagUsageType>("lombok.Getter.flagUsage", "Emit a warning or error if @Getter is used.") {};
+
+ // ----- Setter -----
+
+ /**
+ * lombok configuration: {@code lombok.Setter.flagUsage} = {@code WARNING} | {@code ERROR}.
+ *
+ * If set, <em>any</em> usage of {@code @Setter} results in a warning / error.
+ */
+ public static final ConfigurationKey<FlagUsageType> SETTER_FLAG_USAGE = new ConfigurationKey<FlagUsageType>("lombok.Setter.flagUsage", "Emit a warning or error if @Setter is used.") {};
+
+ // ----- EqualsAndHashCode -----
+
+ /**
+ * lombok configuration: {@code lombok.EqualsAndHashCode.flagUsage} = {@code WARNING} | {@code ERROR}.
+ *
+ * If set, <em>any</em> usage of {@code @EqualsAndHashCode} results in a warning / error.
+ */
+ public static final ConfigurationKey<FlagUsageType> EQUALS_AND_HASH_CODE_FLAG_USAGE = new ConfigurationKey<FlagUsageType>("lombok.EqualsAndHashCode.flagUsage", "Emit a warning or error if @EqualsAndHashCode is used.") {};
+
+ // ----- ToString -----
+
+ /**
+ * lombok configuration: {@code lombok.ToString.doNotUseGetters} = {@code true} | {@code false}.
+ *
+ * For any class without an {@code @ToString} that explicitly defines the {@code doNotUseGetters} option, this value is used.
+ */
+ public static final ConfigurationKey<Boolean> TO_STRING_DO_NOT_USE_GETTERS = new ConfigurationKey<Boolean>("lombok.ToString.doNotUseGetters", "Don't call the getters but use the fields directly in the generated toString method.") {};
+
+ /**
+ * lombok configuration: {@code lombok.ToString.flagUsage} = {@code WARNING} | {@code ERROR}.
+ *
+ * If set, <em>any</em> usage of {@code @ToString} results in a warning / error.
+ */
+ public static final ConfigurationKey<FlagUsageType> TO_STRING_FLAG_USAGE = new ConfigurationKey<FlagUsageType>("lombok.ToString.flagUsage", "Emit a warning or error if @ToString is used.") {};
+
+ /**
+ * lombok configuration: {@code lombok.ToString.includeFieldNames} = {@code true} | {@code false}.
+ *
+ * For any class without an {@code @ToString} that explicitly defines the {@code includeFieldNames} option, this value is used.
+ */
+ public static final ConfigurationKey<Boolean> TO_STRING_INCLUDE_FIELD_NAMES = new ConfigurationKey<Boolean>("lombok.ToString.includeFieldNames", "Include the field names in the generated toString method.") {};
+
+ // ##### Standalones #####
+
+ // ----- Cleanup -----
+
+ /**
+ * lombok configuration: {@code lombok.Cleanup.flagUsage} = {@code WARNING} | {@code ERROR}.
+ *
+ * If set, <em>any</em> usage of {@code @Cleanup} results in a warning / error.
+ */
+ public static final ConfigurationKey<FlagUsageType> CLEANUP_FLAG_USAGE = new ConfigurationKey<FlagUsageType>("lombok.Cleanup.flagUsage", "Emit a warning or error if @Cleanup is used.") {};
+
+ // ----- Delegate -----
+
+ /**
+ * lombok configuration: {@code lombok.Delegate.flagUsage} = {@code WARNING} | {@code ERROR}.
+ *
+ * If set, <em>any</em> usage of {@code @Delegate} results in a warning / error.
+ */
+ public static final ConfigurationKey<FlagUsageType> DELEGATE_FLAG_USAGE = new ConfigurationKey<FlagUsageType>("lombok.Delegate.flagUsage", "Emit a warning or error if @Delegate is used.") {};
+
+ // ----- NonNull -----
+
+ /**
+ * lombok configuration: {@code lombok.NonNull.flagUsage} = {@code WARNING} | {@code ERROR}.
+ *
+ * <em>Implementation note: This field is supposed to be lombok.NonNull itself, but jdk6 and 7 have bugs where fields in annotations don't work well.</em>
+ *
+ * If set, <em>any</em> usage of {@code @NonNull} results in a warning / error.
+ */
+ public static final ConfigurationKey<FlagUsageType> NON_NULL_FLAG_USAGE = new ConfigurationKey<FlagUsageType>("lombok.NonNull.flagUsage", "Emit a warning or error if @NonNull is used.") {};
+
+ // ----- SneakyThrows -----
+
+ /**
+ * lombok configuration: {@code lombok.SneakyThrows.flagUsage} = {@code WARNING} | {@code ERROR}.
+ *
+ * If set, <em>any</em> usage of {@code @SneakyThrows} results in a warning / error.
+ */
+ public static final ConfigurationKey<FlagUsageType> SNEAKY_THROWS_FLAG_USAGE = new ConfigurationKey<FlagUsageType>("lombok.SneakyThrows.flagUsage", "Emit a warning or error if @SneakyThrows is used.") {};
+
+ // ----- Synchronized -----
+
+ /**
+ * lombok configuration: {@code lombok.Synchronized.flagUsage} = {@code WARNING} | {@code ERROR}.
+ *
+ * If set, <em>any</em> usage of {@code @Synchronized} results in a warning / error.
+ */
+ public static final ConfigurationKey<FlagUsageType> SYNCHRONIZED_FLAG_USAGE = new ConfigurationKey<FlagUsageType>("lombok.Synchronized.flagUsage", "Emit a warning or error if @Synchronized is used.") {};
+
+ // ----- val -----
+
+ /**
+ * lombok configuration: {@code lombok.val.flagUsage} = {@code WARNING} | {@code ERROR}.
+ *
+ * If set, <em>any</em> usage of {@code val} results in a warning / error.
+ */
+ public static final ConfigurationKey<FlagUsageType> VAL_FLAG_USAGE = new ConfigurationKey<FlagUsageType>("lombok.val.flagUsage", "Emit a warning or error if 'val' is used.") {};
+
+ // ##### Extern #####
+
+ // ----- Logging -----
+ /**
+ * lombok configuration: {@code lombok.log.flagUsage} = {@code WARNING} | {@code ERROR}.
+ *
+ * If set, <em>any</em> usage of any of the log annotations in {@code lombok.extern}{@code @Slf4j} results in a warning / error.
+ */
+ public static final ConfigurationKey<FlagUsageType> LOG_ANY_FLAG_USAGE = new ConfigurationKey<FlagUsageType>("lombok.log.flagUsage", "Emit a warning or error if any of the log annotations is used.") {};
+
+ /**
+ * lombok configuration: {@code lombok.log.apacheCommons.flagUsage} = {@code WARNING} | {@code ERROR}.
+ *
+ * If set, <em>any</em> usage of {@code @CommonsLog} results in a warning / error.
+ */
+ public static final ConfigurationKey<FlagUsageType> LOG_COMMONS_FLAG_USAGE = new ConfigurationKey<FlagUsageType>("lombok.log.apacheCommons.flagUsage", "Emit a warning or error if @CommonsLog is used.") {};
+
+ /**
+ * lombok configuration: {@code lombok.log.javaUtilLogging.flagUsage} = {@code WARNING} | {@code ERROR}.
+ *
+ * If set, <em>any</em> usage of {@code @Log} results in a warning / error.
+ */
+ public static final ConfigurationKey<FlagUsageType> LOG_JUL_FLAG_USAGE = new ConfigurationKey<FlagUsageType>("lombok.log.javaUtilLogging.flagUsage", "Emit a warning or error if @Log is used.") {};
+
+ /**
+ * lombok configuration: {@code lombok.log.log4j.flagUsage} = {@code WARNING} | {@code ERROR}.
+ *
+ * If set, <em>any</em> usage of {@code @Log4j} results in a warning / error.
+ */
+ public static final ConfigurationKey<FlagUsageType> LOG_LOG4J_FLAG_USAGE = new ConfigurationKey<FlagUsageType>("lombok.log.log4j.flagUsage", "Emit a warning or error if @Log4j is used.") {};
+
+ /**
+ * lombok configuration: {@code lombok.log.log4j2.flagUsage} = {@code WARNING} | {@code ERROR}.
+ *
+ * If set, <em>any</em> usage of {@code @Log4j2} results in a warning / error.
+ */
+ public static final ConfigurationKey<FlagUsageType> LOG_LOG4J2_FLAG_USAGE = new ConfigurationKey<FlagUsageType>("lombok.log.log4j2.flagUsage", "Emit a warning or error if @Log4j2 is used.") {};
+
+ /**
+ * lombok configuration: {@code lombok.log.slf4j.flagUsage} = {@code WARNING} | {@code ERROR}.
+ *
+ * If set, <em>any</em> usage of {@code @Slf4j} results in a warning / error.
+ */
+ public static final ConfigurationKey<FlagUsageType> LOG_SLF4J_FLAG_USAGE = new ConfigurationKey<FlagUsageType>("lombok.log.slf4j.flagUsage", "Emit a warning or error if @Slf4j is used.") {};
+
+ /**
+ * lombok configuration: {@code lombok.log.xslf4j.flagUsage} = {@code WARNING} | {@code ERROR}.
+ *
+ * If set, <em>any</em> usage of {@code @XSlf4j} results in a warning / error.
+ */
+ public static final ConfigurationKey<FlagUsageType> LOG_XSLF4J_FLAG_USAGE = new ConfigurationKey<FlagUsageType>("lombok.log.xslf4j.flagUsage", "Emit a warning or error if @XSlf4j is used.") {};
+
+ /**
+ * lombok configuration: {@code lombok.log.fieldName} = "aJavaIdentifier".
+ *
+ * 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')") {};
+
+ /**
+ * lombok configuration: {@code lombok.log.fieldIsStatic} = {@code true} | {@code false}.
+ *
+ * If not set, or set to {@code true}, the log field generated by the various log annotations will be {@code static}.
+ *
+ * If set to {@code false}, these will be generated as instance fields instead.
+ */
+ public static final ConfigurationKey<Boolean> LOG_ANY_FIELD_IS_STATIC = new ConfigurationKey<Boolean>("lombok.log.fieldIsStatic", "Make the generated logger fields static (default: true).") {};
+
+ // ##### Experimental #####
+
+ /**
+ * lombok configuration: {@code lombok.experimental.flagUsage} = {@code WARNING} | {@code ERROR}.
+ *
+ * If set, <em>any</em> usage of any experimental features (from package {@code lombok.experimental}) that haven't been
+ * promoted to a main feature results in a warning / error.
+ */
+ public static final ConfigurationKey<FlagUsageType> EXPERIMENTAL_FLAG_USAGE = new ConfigurationKey<FlagUsageType>("lombok.experimental.flagUsage", "Emit a warning or error if an experimental feature is used.") {};
+
+ // ----- Accessors -----
+
+ /**
+ * lombok configuration: {@code lombok.Accessors.flagUsage} = {@code WARNING} | {@code ERROR}.
+ *
+ * If set, <em>any</em> usage of {@code @Accessors} results in a warning / error.
+ */
+ public static final ConfigurationKey<FlagUsageType> ACCESSORS_FLAG_USAGE = new ConfigurationKey<FlagUsageType>("lombok.Accessors.flagUsage", "Emit a warning or error if @Accessors is used.") {};
+
+ /**
+ * lombok configuration: {@code lombok.Accessors.prefix} += &lt;String: prefix&gt;.
+ *
+ * For any class without an {@code @Accessors} that explicitly defines the {@code prefix} option, this list of prefixes is used.
+ */
+ public static final ConfigurationKey<List<String>> ACCESSORS_PREFIX = new ConfigurationKey<List<String>>("lombok.Accessors.prefix", "Strip this field prefix, like 'f' or 'm_', from the names of generated getters and setters.") {};
+
+ /**
+ * lombok configuration: {@code lombok.Accessors.chain} = {@code true} | {@code false}.
+ *
+ * For any class without an {@code @Accessors} that explicitly defines the {@code chain} option, this value is used.
+ */
+ public static final ConfigurationKey<Boolean> ACCESSORS_CHAIN = new ConfigurationKey<Boolean>("lombok.Accessors.chain", "Generate setters that return 'this' instead of 'void'.") {};
+
+ /**
+ * lombok configuration: {@code lombok.Accessors.fluent} = {@code true} | {@code false}.
+ *
+ * For any class without an {@code @Accessors} that explicitly defines the {@code fluent} option, this value is used.
+ */
+ public static final ConfigurationKey<Boolean> ACCESSORS_FLUENT = new ConfigurationKey<Boolean>("lombok.Accessors.fluent", "Generate getters and setters using only the field name (no get/set prefix).") {};
+
+ // ----- Builder -----
+
+ /**
+ * lombok configuration: {@code lombok.Builder.flagUsage} = {@code WARNING} | {@code ERROR}.
+ *
+ * If set, <em>any</em> usage of {@code @Builder} results in a warning / error.
+ */
+ public static final ConfigurationKey<FlagUsageType> BUILDER_FLAG_USAGE = new ConfigurationKey<FlagUsageType>("lombok.Builder.flagUsage", "Emit a warning or error if @Builder is used.") {};
+
+ // ----- ExtensionMethod -----
+
+ /**
+ * lombok configuration: {@code lombok.ExtensionMethod.flagUsage} = {@code WARNING} | {@code ERROR}.
+ *
+ * If set, <em>any</em> usage of {@code @ExtensionMethod} results in a warning / error.
+ */
+ public static final ConfigurationKey<FlagUsageType> EXTENSION_METHOD_FLAG_USAGE = new ConfigurationKey<FlagUsageType>("lombok.ExtensionMethod.flagUsage", "Emit a warning or error if @ExtensionMethod is used.") {};
+
+ // ----- FieldDefaults -----
+
+ /**
+ * lombok configuration: {@code lombok.FieldDefaults.flagUsage} = {@code WARNING} | {@code ERROR}.
+ *
+ * If set, <em>any</em> usage of {@code @FieldDefaults} results in a warning / error.
+ */
+ public static final ConfigurationKey<FlagUsageType> FIELD_DEFAULTS_FLAG_USAGE = new ConfigurationKey<FlagUsageType>("lombok.FieldDefaults.flagUsage", "Emit a warning or error if @FieldDefaults is used.") {};
+
+ // ----- Wither -----
+
+ /**
+ * lombok configuration: {@code lombok.Wither.flagUsage} = {@code WARNING} | {@code ERROR}.
+ *
+ * If set, <em>any</em> usage of {@code @Value} results in a warning / error.
+ */
+ public static final ConfigurationKey<FlagUsageType> WITHER_FLAG_USAGE = new ConfigurationKey<FlagUsageType>("lombok.Wither.flagUsage", "Emit a warning or error if @Wither is used.") {};
+
+
+ // ----- Configuration System -----
+
+ /**
+ * lombok configuration: {@code stop-bubbling} = {@code true} | {@code false}.
+ *
+ * If not set, or set to {@code false}, the configuration system will look for {@code lombok.config} files in the parent directory.
+ *
+ * If set to {@code true}, no futher {@code lombok.config} files will be checked.
+ */
+ public static final ConfigurationKey<Boolean> STOP_BUBBLING = new ConfigurationKey<Boolean>("stop-bubbling", "Tell the configuration system it should stop looking for other configuration files (default: false).") {};
+}
diff --git a/src/core/lombok/Delegate.java b/src/core/lombok/Delegate.java
index b599e4f0..534cfb3d 100644
--- a/src/core/lombok/Delegate.java
+++ b/src/core/lombok/Delegate.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010-2012 The Project Lombok Authors.
+ * Copyright (C) 2010-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
diff --git a/src/core/lombok/EqualsAndHashCode.java b/src/core/lombok/EqualsAndHashCode.java
index 8b809c4b..60ed9e7a 100644
--- a/src/core/lombok/EqualsAndHashCode.java
+++ b/src/core/lombok/EqualsAndHashCode.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009-2012 The Project Lombok Authors.
+ * Copyright (C) 2009-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
diff --git a/src/core/lombok/NonNull.java b/src/core/lombok/NonNull.java
index 96813170..58538583 100644
--- a/src/core/lombok/NonNull.java
+++ b/src/core/lombok/NonNull.java
@@ -44,4 +44,5 @@ import java.lang.annotation.Target;
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.LOCAL_VARIABLE})
@Retention(RetentionPolicy.CLASS)
@Documented
-public @interface NonNull {}
+public @interface NonNull {
+}
diff --git a/src/core/lombok/SneakyThrows.java b/src/core/lombok/SneakyThrows.java
index 4bd79065..929b4578 100644
--- a/src/core/lombok/SneakyThrows.java
+++ b/src/core/lombok/SneakyThrows.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009-2012 The Project Lombok Authors.
+ * Copyright (C) 2009-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
diff --git a/src/core/lombok/Synchronized.java b/src/core/lombok/Synchronized.java
index fadea89a..c5601a0c 100644
--- a/src/core/lombok/Synchronized.java
+++ b/src/core/lombok/Synchronized.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009-2012 The Project Lombok Authors.
+ * Copyright (C) 2009-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
diff --git a/src/core/lombok/ToString.java b/src/core/lombok/ToString.java
index e39b9858..e87c71e7 100644
--- a/src/core/lombok/ToString.java
+++ b/src/core/lombok/ToString.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009-2012 The Project Lombok Authors.
+ * Copyright (C) 2009-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
diff --git a/src/core/lombok/core/AST.java b/src/core/lombok/core/AST.java
index 6fed0252..50eeb399 100644
--- a/src/core/lombok/core/AST.java
+++ b/src/core/lombok/core/AST.java
@@ -28,6 +28,7 @@ import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
+import java.net.URI;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
@@ -35,6 +36,8 @@ import java.util.IdentityHashMap;
import java.util.List;
import java.util.Map;
+import lombok.core.configuration.ConfigurationKey;
+
/**
* Lombok wraps the AST produced by a target platform into its own AST system, mostly because both Eclipse and javac
* do not allow upward traversal (from a method to its owning type, for example).
@@ -64,6 +67,13 @@ public abstract class AST<A extends AST<A, L, N>, L extends LombokNode<A, L, N>,
this.imports = imports;
}
+ /**
+ * Attempts to find the absolute path (in URI form) to the source file represented by this AST.
+ *
+ * May return {@code null} if this cannot be done. We don't yet know under which conditions this will happen.
+ */
+ public abstract URI getAbsoluteFileLocation();
+
public void setChanged() {
this.changed = true;
}
@@ -407,4 +417,8 @@ public abstract class AST<A extends AST<A, L, N>, L extends LombokNode<A, L, N>,
buildWithCollection(nodeType, v, list, dim-1);
}
}
+
+ public final <T> T readConfiguration(ConfigurationKey<T> key) {
+ return LombokConfiguration.read(key, this);
+ }
}
diff --git a/src/core/lombok/core/FlagUsageType.java b/src/core/lombok/core/FlagUsageType.java
new file mode 100644
index 00000000..42770ef1
--- /dev/null
+++ b/src/core/lombok/core/FlagUsageType.java
@@ -0,0 +1,6 @@
+package lombok.core;
+
+/** Used for lombok configuration to flag usages of certain lombok feature. */
+public enum FlagUsageType {
+ WARNING, ERROR;
+}
diff --git a/src/core/lombok/core/LombokConfiguration.java b/src/core/lombok/core/LombokConfiguration.java
new file mode 100644
index 00000000..137a8a83
--- /dev/null
+++ b/src/core/lombok/core/LombokConfiguration.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2013-2014 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;
+
+import lombok.core.configuration.BubblingConfigurationResolver;
+import lombok.core.configuration.ConfigurationKey;
+import lombok.core.configuration.ConfigurationProblemReporter;
+import lombok.core.configuration.ConfigurationResolver;
+import lombok.core.configuration.ConfigurationResolverFactory;
+import lombok.core.configuration.FileSystemSourceCache;
+
+public class LombokConfiguration {
+ private static FileSystemSourceCache cache = new FileSystemSourceCache();
+ private static ConfigurationResolverFactory configurationResolverFactory = createFileSystemBubblingResolverFactory();
+
+ private LombokConfiguration() {
+ // prevent instantiation
+ }
+
+ public static void overrideConfigurationResolverFactory(ConfigurationResolverFactory crf) {
+ configurationResolverFactory = crf == null ? createFileSystemBubblingResolverFactory() : crf;
+ }
+
+ static <T> T read(ConfigurationKey<T> key, AST<?, ?, ?> ast) {
+ return configurationResolverFactory.createResolver(ast).resolve(key);
+ }
+
+ private static ConfigurationResolverFactory createFileSystemBubblingResolverFactory() {
+ return new ConfigurationResolverFactory() {
+ @Override public ConfigurationResolver createResolver(AST<?, ?, ?> ast) {
+ return new BubblingConfigurationResolver(cache.sourcesForJavaFile(ast.getAbsoluteFileLocation(), ConfigurationProblemReporter.CONSOLE));
+ }
+ };
+ }
+}
diff --git a/src/core/lombok/core/TransformationsUtil.java b/src/core/lombok/core/TransformationsUtil.java
deleted file mode 100644
index 8c7fbd3f..00000000
--- a/src/core/lombok/core/TransformationsUtil.java
+++ /dev/null
@@ -1,306 +0,0 @@
-/*
- * Copyright (C) 2009-2012 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;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-import java.util.regex.Pattern;
-
-import lombok.AllArgsConstructor;
-import lombok.Data;
-import lombok.EqualsAndHashCode;
-import lombok.Getter;
-import lombok.NoArgsConstructor;
-import lombok.RequiredArgsConstructor;
-import lombok.Setter;
-import lombok.ToString;
-import lombok.Value;
-import lombok.experimental.Accessors;
-import lombok.experimental.FieldDefaults;
-import lombok.experimental.Wither;
-
-/**
- * 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).
- */
-public class TransformationsUtil {
- private TransformationsUtil() {
- //Prevent instantiation
- }
-
- @SuppressWarnings({"all", "unchecked", "deprecation"})
- public static final List<Class<? extends java.lang.annotation.Annotation>> INVALID_ON_BUILDERS = Collections.unmodifiableList(
- Arrays.<Class<? extends java.lang.annotation.Annotation>>asList(
- Getter.class, Setter.class, Wither.class, ToString.class, EqualsAndHashCode.class,
- RequiredArgsConstructor.class, AllArgsConstructor.class, NoArgsConstructor.class,
- Data.class, Value.class, lombok.experimental.Value.class, FieldDefaults.class));
-
- /**
- * Given the name of a field, return the 'base name' of that field. For example, {@code fFoobar} becomes {@code foobar} if {@code f} is in the prefix list.
- * For prefixes that end in a letter character, the next character must be a non-lowercase character (i.e. {@code hashCode} is not {@code ashCode} even if
- * {@code h} is in the prefix list, but {@code hAshcode} would become {@code ashCode}). The first prefix that matches is used. If the prefix list is empty,
- * or the empty string is in the prefix list and no prefix before it matches, the fieldName will be returned verbatim.
- *
- * If no prefix matches and the empty string is not in the prefix list and the prefix list is not empty, {@code null} is returned.
- *
- * @param fieldName The full name of a field.
- * @param prefixes A list of prefixes, usually provided by the {@code Accessors} settings annotation, listing field prefixes.
- * @return The base name of the field.
- */
- public static CharSequence removePrefix(CharSequence fieldName, String[] prefixes) {
- if (prefixes == null || prefixes.length == 0) return fieldName;
-
- fieldName = fieldName.toString();
-
- outer:
- for (String prefix : prefixes) {
- if (prefix.length() == 0) return fieldName;
- if (fieldName.length() <= prefix.length()) continue outer;
- for (int i = 0; i < prefix.length(); i++) {
- if (fieldName.charAt(i) != prefix.charAt(i)) continue outer;
- }
- char followupChar = fieldName.charAt(prefix.length());
- // if prefix is a letter then follow up letter needs to not be lowercase, i.e. 'foo' is not a match
- // as field named 'oo' with prefix 'f', but 'fOo' would be.
- if (Character.isLetter(prefix.charAt(prefix.length() - 1)) &&
- Character.isLowerCase(followupChar)) continue outer;
- return "" + Character.toLowerCase(followupChar) + fieldName.subSequence(prefix.length() + 1, fieldName.length());
- }
-
- return null;
- }
-
- /* NB: 'notnull' is not part of the pattern because there are lots of @NotNull annotations out there that are crappily named and actually mean
- something else, such as 'this field must not be null _when saved to the db_ but its perfectly okay to start out as such, and a no-args
- constructor and the implied starts-out-as-null state that goes with it is in fact mandatory' which happens with javax.validation.constraints.NotNull.
- Various problems with spring have also been reported. See issue #287, issue #271, and issue #43. */
-
- /** Matches the simple part of any annotation that lombok considers as indicative of NonNull status. */
- public static final Pattern NON_NULL_PATTERN = Pattern.compile("^(?:nonnull)$", Pattern.CASE_INSENSITIVE);
-
- /** Matches the simple part of any annotation that lombok considers as indicative of Nullable status. */
- public static final Pattern NULLABLE_PATTERN = Pattern.compile("^(?:nullable|checkfornull)$", Pattern.CASE_INSENSITIVE);
-
- /**
- * Generates a getter name from a given field name.
- *
- * Strategy:
- * <ul>
- * <li>Reduce the field's name to its base name by stripping off any prefix (from {@code Accessors}). If the field name does not fit
- * the prefix list, this method immediately returns {@code null}.</li>
- * <li>If {@code Accessors} has {@code fluent=true}, then return the basename.</li>
- * <li>Pick a prefix. 'get' normally, but 'is' if {@code isBoolean} is true.</li>
- * <li>Only if {@code isBoolean} is true: Check if the field starts with {@code is} followed by a non-lowercase character. If so, return the field name verbatim.</li>
- * <li>Check if the first character of the field is lowercase. If so, check if the second character
- * exists and is title or upper case. If so, uppercase the first character. If not, titlecase the first character.</li>
- * <li>Return the prefix plus the possibly title/uppercased first character, and the rest of the field name.</li>
- * </ul>
- *
- * @param accessors Accessors configuration.
- * @param fieldName the name of the field.
- * @param isBoolean if the field is of type 'boolean'. For fields of type {@code java.lang.Boolean}, you should provide {@code false}.
- * @return The getter name for this field, or {@code null} if this field does not fit expected patterns and therefore cannot be turned into a getter name.
- */
- public static String toGetterName(AnnotationValues<Accessors> accessors, CharSequence fieldName, boolean isBoolean) {
- return toAccessorName(accessors, fieldName, isBoolean, "is", "get", true);
- }
-
- /**
- * Generates a setter name from a given field name.
- *
- * Strategy:
- * <ul>
- * <li>Reduce the field's name to its base name by stripping off any prefix (from {@code Accessors}). If the field name does not fit
- * the prefix list, this method immediately returns {@code null}.</li>
- * <li>If {@code Accessors} has {@code fluent=true}, then return the basename.</li>
- * <li>Only if {@code isBoolean} is true: Check if the field starts with {@code is} followed by a non-lowercase character.
- * If so, replace {@code is} with {@code set} and return that.</li>
- * <li>Check if the first character of the field is lowercase. If so, check if the second character
- * exists and is title or upper case. If so, uppercase the first character. If not, titlecase the first character.</li>
- * <li>Return {@code "set"} plus the possibly title/uppercased first character, and the rest of the field name.</li>
- * </ul>
- *
- * @param accessors Accessors configuration.
- * @param fieldName the name of the field.
- * @param isBoolean if the field is of type 'boolean'. For fields of type {@code java.lang.Boolean}, you should provide {@code false}.
- * @return The setter name for this field, or {@code null} if this field does not fit expected patterns and therefore cannot be turned into a getter name.
- */
- public static String toSetterName(AnnotationValues<Accessors> accessors, CharSequence fieldName, boolean isBoolean) {
- return toAccessorName(accessors, fieldName, isBoolean, "set", "set", true);
- }
-
- /**
- * Generates a wither name from a given field name.
- *
- * Strategy:
- * <ul>
- * <li>Reduce the field's name to its base name by stripping off any prefix (from {@code Accessors}). If the field name does not fit
- * the prefix list, this method immediately returns {@code null}.</li>
- * <li>Only if {@code isBoolean} is true: Check if the field starts with {@code is} followed by a non-lowercase character.
- * If so, replace {@code is} with {@code with} and return that.</li>
- * <li>Check if the first character of the field is lowercase. If so, check if the second character
- * exists and is title or upper case. If so, uppercase the first character. If not, titlecase the first character.</li>
- * <li>Return {@code "with"} plus the possibly title/uppercased first character, and the rest of the field name.</li>
- * </ul>
- *
- * @param accessors Accessors configuration.
- * @param fieldName the name of the field.
- * @param isBoolean if the field is of type 'boolean'. For fields of type {@code java.lang.Boolean}, you should provide {@code false}.
- * @return The wither name for this field, or {@code null} if this field does not fit expected patterns and therefore cannot be turned into a getter name.
- */
- public static String toWitherName(AnnotationValues<Accessors> accessors, CharSequence fieldName, boolean isBoolean) {
- return toAccessorName(accessors, fieldName, isBoolean, "with", "with", false);
- }
-
- private static String toAccessorName(AnnotationValues<Accessors> accessors, CharSequence fieldName, boolean isBoolean,
- String booleanPrefix, String normalPrefix, boolean adhereToFluent) {
-
- fieldName = fieldName.toString();
- if (fieldName.length() == 0) return null;
-
- Accessors ac = accessors == null ? null : accessors.getInstance();
- fieldName = removePrefix(fieldName, ac == null ? new String[0] : ac.prefix());
- if (fieldName == null) return null;
-
- String fName = fieldName.toString();
- if (adhereToFluent && ac != null && ac.fluent()) return fName;
-
- if (isBoolean && fName.startsWith("is") && fieldName.length() > 2 && !Character.isLowerCase(fieldName.charAt(2))) {
- // The field is for example named 'isRunning'.
- return booleanPrefix + fName.substring(2);
- }
-
- return buildName(isBoolean ? booleanPrefix : normalPrefix, fName);
- }
-
- /**
- * 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 accessors Accessors configuration.
- * @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(AnnotationValues<Accessors> accessors, CharSequence fieldName, boolean isBoolean) {
- return toAllAccessorNames(accessors, fieldName, isBoolean, "is", "get", true);
- }
-
- /**
- * 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 accessors Accessors configuration.
- * @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(AnnotationValues<Accessors> accessors, CharSequence fieldName, boolean isBoolean) {
- return toAllAccessorNames(accessors, fieldName, isBoolean, "set", "set", true);
- }
-
- /**
- * Returns all names of methods that would represent the wither for a field with the provided name.
- *
- * For example if {@code isBoolean} is true, then a field named {@code isRunning} would produce:<br />
- * {@code [withRunning, withIsRunning]}
- *
- * @param accessors Accessors configuration.
- * @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> toAllWitherNames(AnnotationValues<Accessors> accessors, CharSequence fieldName, boolean isBoolean) {
- return toAllAccessorNames(accessors, fieldName, isBoolean, "with", "with", false);
- }
-
- private static List<String> toAllAccessorNames(AnnotationValues<Accessors> accessors, CharSequence fieldName, boolean isBoolean,
- String booleanPrefix, String normalPrefix, boolean adhereToFluent) {
-
- if (!isBoolean) {
- String accessorName = toAccessorName(accessors, fieldName, false, booleanPrefix, normalPrefix, adhereToFluent);
- return (accessorName == null) ? Collections.<String>emptyList() : Collections.singletonList(accessorName);
- }
-
- Accessors acc = accessors.getInstance();
- fieldName = removePrefix(fieldName, acc.prefix());
- if (fieldName == null) return Collections.emptyList();
-
- List<String> baseNames = toBaseNames(fieldName, isBoolean, acc.fluent());
-
- Set<String> names = new HashSet<String>();
- for (String baseName : baseNames) {
- if (adhereToFluent && acc.fluent()) {
- names.add(baseName);
- } else {
- names.add(buildName(normalPrefix, baseName));
- if (!normalPrefix.equals(booleanPrefix)) names.add(buildName(booleanPrefix, baseName));
- }
- }
-
- return new ArrayList<String>(names);
-
- }
-
- private static List<String> toBaseNames(CharSequence fieldName, boolean isBoolean, boolean fluent) {
- List<String> baseNames = new ArrayList<String>();
- baseNames.add(fieldName.toString());
-
- // isPrefix = field is called something like 'isRunning', so 'running' could also be the fieldname.
- String fName = fieldName.toString();
- if (fName.startsWith("is") && fName.length() > 2 && !Character.isLowerCase(fName.charAt(2))) {
- String baseName = fName.substring(2);
- if (fluent) {
- baseNames.add("" + Character.toLowerCase(baseName.charAt(0)) + baseName.substring(1));
- } else {
- baseNames.add(baseName);
- }
- }
-
- return baseNames;
- }
-
- /**
- * @param prefix Something like {@code get} or {@code set} or {@code is}.
- * @param suffix Something like {@code running}.
- * @return prefix + smartly title-cased suffix. For example, {@code setRunning}.
- */
- private static String buildName(String prefix, String suffix) {
- if (suffix.length() == 0) return prefix;
- if (prefix.length() == 0) return suffix;
-
- char first = suffix.charAt(0);
- if (Character.isLowerCase(first)) {
- boolean useUpperCase = suffix.length() > 2 &&
- (Character.isTitleCase(suffix.charAt(1)) || Character.isUpperCase(suffix.charAt(1)));
- suffix = String.format("%s%s",
- useUpperCase ? Character.toUpperCase(first) : Character.toTitleCase(first),
- suffix.subSequence(1, suffix.length()));
- }
- return String.format("%s%s", prefix, suffix);
- }
-}
diff --git a/src/core/lombok/core/configuration/BubblingConfigurationResolver.java b/src/core/lombok/core/configuration/BubblingConfigurationResolver.java
new file mode 100644
index 00000000..f96b4468
--- /dev/null
+++ b/src/core/lombok/core/configuration/BubblingConfigurationResolver.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2014 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 java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import lombok.core.configuration.ConfigurationSource.ListModification;
+import lombok.core.configuration.ConfigurationSource.Result;
+
+public class BubblingConfigurationResolver implements ConfigurationResolver {
+
+ private final Iterable<ConfigurationSource> sources;
+
+ public BubblingConfigurationResolver(Iterable<ConfigurationSource> sources) {
+ this.sources = sources;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public <T> T resolve(ConfigurationKey<T> key) {
+ boolean isList = key.getType().isList();
+ List<List<ListModification>> listModificationsList = null;
+ for (ConfigurationSource source : sources) {
+ Result result = source.resolve(key);
+ if (result == null) continue;
+ if (isList) {
+ if (listModificationsList == null) {
+ listModificationsList = new ArrayList<List<ListModification>>();
+ }
+ listModificationsList.add((List<ListModification>)result.getValue());
+ }
+ if (result.isAuthoritative()) {
+ if (isList) {
+ break;
+ }
+ return (T) result.getValue();
+ }
+ }
+ if (!isList) {
+ return null;
+ }
+ if (listModificationsList == null) {
+ return (T) Collections.emptyList();
+ }
+ List<Object> listValues = new ArrayList<Object>();
+ Collections.reverse(listModificationsList);
+ for (List<ListModification> listModifications : listModificationsList) {
+ if (listModifications != null) for (ListModification modification : listModifications) {
+ listValues.remove(modification.getValue());
+ if (modification.isAdded()) {
+ listValues.add(modification.getValue());
+ }
+ }
+ }
+ return (T) listValues;
+ }
+}
diff --git a/src/core/lombok/core/configuration/ConfigurationApp.java b/src/core/lombok/core/configuration/ConfigurationApp.java
new file mode 100644
index 00000000..e441b4de
--- /dev/null
+++ b/src/core/lombok/core/configuration/ConfigurationApp.java
@@ -0,0 +1,376 @@
+/*
+ * Copyright (C) 2014 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 static lombok.core.configuration.FileSystemSourceCache.fileToString;
+
+import java.io.File;
+import java.io.PrintStream;
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.TreeMap;
+import java.util.TreeSet;
+
+import lombok.ConfigurationKeys;
+import lombok.core.LombokApp;
+import lombok.core.configuration.ConfigurationParser.Collector;
+
+import org.mangosdk.spi.ProviderFor;
+
+import com.zwitserloot.cmdreader.CmdReader;
+import com.zwitserloot.cmdreader.Description;
+import com.zwitserloot.cmdreader.Excludes;
+import com.zwitserloot.cmdreader.InvalidCommandLineException;
+import com.zwitserloot.cmdreader.Mandatory;
+import com.zwitserloot.cmdreader.Sequential;
+import com.zwitserloot.cmdreader.Shorthand;
+
+@ProviderFor(LombokApp.class)
+public class ConfigurationApp extends LombokApp {
+ private static final URI NO_CONFIG = URI.create("");
+
+ private PrintStream out = System.out;
+ private PrintStream err = System.err;
+
+ @Override public String getAppName() {
+ return "config";
+ }
+
+ @Override public String getAppDescription() {
+ return "Prints the configurations for the provided paths to standard out.";
+ }
+
+ @Override public List<String> getAppAliases() {
+ return Arrays.asList("configuration", "config", "conf", "settings");
+ }
+
+ public static class CmdArgs {
+ @Sequential
+ @Mandatory(onlyIfNot={"help", "generate"})
+ @Description("Paths to java files or directories the configuration is to be printed for.")
+ private List<String> paths = new ArrayList<String>();
+
+ @Shorthand("g")
+ @Excludes("paths")
+ @Description("Generates a list containing all the available configuration parameters. Add --verbose to print more information.")
+ boolean generate = false;
+
+ @Shorthand("v")
+ @Description("Displays more information.")
+ boolean verbose = false;
+
+ @Shorthand("k")
+ @Description("Limit the result to these keys.")
+ private List<String> key = new ArrayList<String>();
+
+ @Shorthand({"h", "?"})
+ @Description("Shows this help text.")
+ boolean help = false;
+ }
+
+ @Override public int runApp(List<String> raw) throws Exception {
+ CmdReader<CmdArgs> reader = CmdReader.of(CmdArgs.class);
+ CmdArgs args;
+ try {
+ args = reader.make(raw.toArray(new String[0]));
+ if (args.help) {
+ out.println(reader.generateCommandLineHelp("java -jar lombok.jar configuration"));
+ return 0;
+ }
+ } catch (InvalidCommandLineException e) {
+ err.println(e.getMessage());
+ err.println(reader.generateCommandLineHelp("java -jar lombok.jar configuration"));
+ return 1;
+ }
+
+ ConfigurationKeysLoader.LoaderLoader.loadAllConfigurationKeys();
+ Collection<ConfigurationKey<?>> keys = checkKeys(args.key);
+ if (keys == null) return 1;
+
+ boolean verbose = args.verbose;
+ if (args.generate) {
+ return generate(keys, verbose);
+ }
+
+ return display(keys, verbose, args.paths, !args.key.isEmpty());
+ }
+
+ public ConfigurationApp redirectOutput(PrintStream out, PrintStream err) {
+ if (out != null) this.out = out;
+ if (err != null) this.err = err;
+ return this;
+ }
+
+ public int generate(Collection<ConfigurationKey<?>> keys, boolean verbose) {
+ for (ConfigurationKey<?> key : keys) {
+ String keyName = key.getKeyName();
+ ConfigurationDataType type = key.getType();
+ String description = key.getDescription();
+ boolean hasDescription = description != null && !description.isEmpty();
+ if (!verbose) {
+ out.println(keyName);
+ if (hasDescription) {
+ out.print(" ");
+ out.println(description);
+ }
+ out.println();
+ continue;
+ }
+ out.printf("##%n## Key : %s%n## Type: %s%n", keyName, type);
+ if (hasDescription) {
+ out.printf("##%n## %s%n", description);
+ }
+ out.printf("##%n## Examples:%n#%n");
+ out.printf("# clear %s%n", keyName);
+ String exampleValue = type.getParser().exampleValue();
+ if (type.isList()) {
+ out.printf("# %s += %s%n", keyName, exampleValue);
+ out.printf("# %s -= %s%n", keyName, exampleValue);
+ } else {
+ out.printf("# %s = %s%n", keyName, exampleValue);
+ }
+ out.printf("#%n%n");
+ }
+ if (!verbose) {
+ out.println("Use --verbose for more information.");
+ }
+ return 0;
+ }
+
+ public int display(Collection<ConfigurationKey<?>> keys, boolean verbose, Collection<String> argsPaths, boolean explicitKeys) throws Exception {
+ TreeMap<URI, Set<String>> sharedDirectories = findSharedDirectories(argsPaths);
+
+ if (sharedDirectories == null) return 1;
+
+ Set<String> none = sharedDirectories.remove(NO_CONFIG);
+ if (none != null) {
+ if (none.size() == 1) {
+ out.printf("No 'lombok.config' found for '%s'.%n", none.iterator().next());
+ } else {
+ out.println("No 'lombok.config' found for: ");
+ for (String path : none) out.printf("- %s%n", path);
+ }
+ }
+
+ final List<String> problems = new ArrayList<String>();
+ ConfigurationProblemReporter reporter = new ConfigurationProblemReporter() {
+ @Override public void report(String sourceDescription, String problem, int lineNumber, CharSequence line) {
+ problems.add(String.format("%s: %s (%s:%d)", problem, line, sourceDescription, lineNumber));
+ }
+ };
+
+ FileSystemSourceCache cache = new FileSystemSourceCache();
+ boolean first = true;
+ for (Entry<URI, Set<String>> entry : sharedDirectories.entrySet()) {
+ if (!first) {
+ out.printf("%n%n");
+ }
+ Set<String> paths = entry.getValue();
+ if (paths.size() == 1) {
+ if (!(argsPaths.size() == 1)) out.printf("Configuration for '%s'.%n%n", paths.iterator().next());
+ } else {
+ out.printf("Configuration for:%n", paths.iterator().next());
+ for (String path : paths) out.printf("- %s%n", path);
+ out.println();
+ }
+ URI directory = entry.getKey();
+ ConfigurationResolver resolver = new BubblingConfigurationResolver(cache.sourcesForDirectory(directory, reporter));
+ Map<ConfigurationKey<?>, ? extends Collection<String>> traces = trace(keys, directory);
+ boolean printed = false;
+ for (ConfigurationKey<?> key : keys) {
+ Object value = resolver.resolve(key);
+ Collection<String> modifications = traces.get(key);
+ if (!modifications.isEmpty() || explicitKeys) {
+ if (printed && verbose) out.println();
+ printValue(key, value, verbose, modifications);
+ printed = true;
+ }
+ }
+ if (!printed) out.println("<default>");
+ first = false;
+ }
+
+ if (!problems.isEmpty()) {
+ out.printf("%nProblems in the configuration files: %n");
+ for (String problem : problems) out.printf("- %s%n", problem);
+ }
+
+ return 0;
+ }
+
+ private void printValue(ConfigurationKey<?> key, Object value, boolean verbose, Collection<String> history) {
+ if (verbose) out.printf("# %s%n", key.getDescription());
+ if (value == null) {
+ out.printf("clear %s%n", key.getKeyName());
+ } else if (value instanceof List<?>) {
+ List<?> list = (List<?>)value;
+ if (list.isEmpty()) out.printf("clear %s%n", key.getKeyName());
+ for (Object element : list) out.printf("%s += %s%n", key.getKeyName(), element);
+ } else {
+ out.printf("%s = %s%n", key.getKeyName(), value);
+ }
+ if (!verbose) return;
+ for (String modification : history) out.printf("# %s%n", modification);
+ }
+
+ private static final ConfigurationProblemReporter VOID = new ConfigurationProblemReporter() {
+ @Override public void report(String sourceDescription, String problem, int lineNumber, CharSequence line) {}
+ };
+
+ private Map<ConfigurationKey<?>, ? extends Collection<String>> trace(Collection<ConfigurationKey<?>> keys, URI directory) throws Exception {
+ Map<ConfigurationKey<?>, List<String>> result = new HashMap<ConfigurationKey<?>, List<String>>();
+ for (ConfigurationKey<?> key : keys) result.put(key, new ArrayList<String>());
+ Set<ConfigurationKey<?>> used = new HashSet<ConfigurationKey<?>>();
+
+ boolean stopBubbling = false;
+ String previousFileName = null;
+ for (File currentDirectory = new File(directory); currentDirectory != null && !stopBubbling; currentDirectory = currentDirectory.getParentFile()) {
+ File configFile = new File(currentDirectory, "lombok.config");
+ if (!configFile.exists() || !configFile.isFile()) continue;
+
+ Map<ConfigurationKey<?>, List<String>> traces = trace(fileToString(configFile), configFile.getAbsolutePath(), keys);
+
+ stopBubbling = stopBubbling(traces.get(ConfigurationKeys.STOP_BUBBLING));
+ for (ConfigurationKey<?> key : keys) {
+ List<String> modifications = traces.get(key);
+ if (modifications == null) {
+ modifications = new ArrayList<String>();
+ modifications.add(" <'" + key.getKeyName() + "' not mentioned>");
+ } else {
+ used.add(key);
+ }
+ if (previousFileName != null) {
+ modifications.add("");
+ modifications.add(previousFileName + ":");
+ }
+ result.get(key).addAll(0, modifications);
+ }
+ previousFileName = configFile.getAbsolutePath();
+ }
+ for (ConfigurationKey<?> key : keys) {
+ if (used.contains(key)) {
+ result.get(key).add(0, previousFileName + (stopBubbling ? " (stopped bubbling):" : ":"));
+ } else {
+ result.put(key, Collections.<String>emptyList());
+ }
+ }
+ return result;
+ }
+
+ private Map<ConfigurationKey<?>, List<String>> trace(String content, String contentDescription, final Collection<ConfigurationKey<?>> keys) {
+ final Map<ConfigurationKey<?>, List<String>> result = new HashMap<ConfigurationKey<?>, List<String>>();
+
+ Collector collector = new Collector() {
+ @Override public void clear(ConfigurationKey<?> key, String contentDescription, int lineNumber) {
+ trace(key, "clear " + key.getKeyName(), lineNumber);
+ }
+
+ @Override public void set(ConfigurationKey<?> key, Object value, String contentDescription, int lineNumber) {
+ trace(key, key.getKeyName() + " = " + value, lineNumber);
+ }
+
+ @Override public void add(ConfigurationKey<?> key, Object value, String contentDescription, int lineNumber) {
+ trace(key, key.getKeyName() + " += " + value, lineNumber);
+ }
+
+ @Override public void remove(ConfigurationKey<?> key, Object value, String contentDescription, int lineNumber) {
+ trace(key, key.getKeyName() + " -= " + value, lineNumber);
+ }
+
+ private void trace(ConfigurationKey<?> key, String message, int lineNumber) {
+ if (!keys.contains(key)) return;
+ List<String> traces = result.get(key);
+ if (traces == null) {
+ traces = new ArrayList<String>();
+ result.put(key, traces);
+ }
+ traces.add(String.format("%4d: %s", lineNumber, message));
+ }
+ };
+ new ConfigurationParser(VOID).parse(content, contentDescription, collector);
+ return result;
+ }
+
+ private boolean stopBubbling(List<String> stops) {
+ return stops != null && !stops.isEmpty() && stops.get(stops.size() -1).endsWith("true");
+ }
+
+ private Collection<ConfigurationKey<?>> checkKeys(List<String> keyList) {
+ Map<String, ConfigurationKey<?>> registeredKeys = ConfigurationKey.registeredKeys();
+ if (keyList.isEmpty()) return registeredKeys.values();
+
+ Collection<ConfigurationKey<?>> keys = new ArrayList<ConfigurationKey<?>>();
+ for (String keyName : keyList) {
+ ConfigurationKey<?> key = registeredKeys.get(keyName);
+ if (key == null) {
+ err.printf("Unknown key '%s'%n", keyName);
+ return null;
+ }
+ keys.remove(key);
+ keys.add(key);
+ }
+ return keys;
+ }
+
+ private TreeMap<URI, Set<String>> findSharedDirectories(Collection<String> paths) {
+ TreeMap<URI,Set<String>> sharedDirectories = new TreeMap<URI, Set<String>>(new Comparator<URI>() {
+ @Override public int compare(URI o1, URI o2) {
+ return o1.toString().compareTo(o2.toString());
+ }
+ });
+ for (String path : paths) {
+ File file = new File(path);
+ if (!file.exists()) {
+ err.printf("File not found: '%s'%n", path);
+ return null;
+ }
+ URI first = findFirstLombokDirectory(file);
+ Set<String> sharedBy = sharedDirectories.get(first);
+ if (sharedBy == null) {
+ sharedBy = new TreeSet<String>();
+ sharedDirectories.put(first, sharedBy);
+ }
+ sharedBy.add(path);
+ }
+ return sharedDirectories;
+ }
+
+ private URI findFirstLombokDirectory(File file) {
+ File current = new File(file.toURI().normalize());
+ if (file.isFile()) current = current.getParentFile();
+ while (current != null) {
+ if (new File(current, "lombok.config").exists()) return current.toURI();
+ current = current.getParentFile();
+ }
+ return NO_CONFIG;
+ }
+}
diff --git a/src/core/lombok/core/configuration/ConfigurationDataType.java b/src/core/lombok/core/configuration/ConfigurationDataType.java
new file mode 100644
index 00000000..ca0302ff
--- /dev/null
+++ b/src/core/lombok/core/configuration/ConfigurationDataType.java
@@ -0,0 +1,182 @@
+/*
+ * 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 java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public final class ConfigurationDataType {
+ private static final Map<Class<?>, ConfigurationValueParser> SIMPLE_TYPES;
+ static {
+ Map<Class<?>, ConfigurationValueParser> map = new HashMap<Class<?>, ConfigurationValueParser>();
+ map.put(String.class, new ConfigurationValueParser() {
+ @Override public Object parse(String value) {
+ return value;
+ }
+ @Override public String description() {
+ return "string";
+ }
+ @Override public String exampleValue() {
+ return "<text>";
+ }
+ });
+ map.put(Integer.class, new ConfigurationValueParser() {
+ @Override public Object parse(String value) {
+ return Integer.parseInt(value);
+ }
+ @Override public String description() {
+ return "int";
+ }
+ @Override public String exampleValue() {
+ return "<int>";
+ }
+ });
+ map.put(Long.class, new ConfigurationValueParser() {
+ @Override public Object parse(String value) {
+ return Long.parseLong(value);
+ }
+ @Override public String description() {
+ return "long";
+ }
+ @Override public String exampleValue() {
+ return "<long>";
+ }
+ });
+ map.put(Double.class, new ConfigurationValueParser() {
+ @Override public Object parse(String value) {
+ return Double.parseDouble(value);
+ }
+ @Override public String description() {
+ return "double";
+ }
+ @Override public String exampleValue() {
+ return "<double>";
+ }
+ });
+ map.put(Boolean.class, new ConfigurationValueParser() {
+ @Override public Object parse(String value) {
+ return Boolean.parseBoolean(value);
+ }
+ @Override public String description() {
+ return "boolean";
+ }
+ @Override public String exampleValue() {
+ return "[false | true]";
+ }
+ });
+ map.put(TypeName.class, new ConfigurationValueParser() {
+ @Override public Object parse(String value) {
+ return TypeName.valueOf(value);
+ }
+ @Override public String description() {
+ return "type-name";
+ }
+ @Override public String exampleValue() {
+ return "<fully.qualified.Type>";
+ }
+ });
+ SIMPLE_TYPES = map;
+ }
+
+ private static ConfigurationValueParser enumParser(Object enumType) {
+ @SuppressWarnings("rawtypes") final Class rawType = (Class)enumType;
+ return new ConfigurationValueParser(){
+ @SuppressWarnings("unchecked")
+ @Override public Object parse(String value) {
+ try {
+ return Enum.valueOf(rawType, value);
+ } catch (Exception e) {
+ return Enum.valueOf(rawType, value.toUpperCase());
+ }
+ }
+ @Override public String description() {
+ return "enum (" + rawType.getName() + ")";
+ }
+ @Override public String exampleValue() {
+ return Arrays.toString(rawType.getEnumConstants()).replace(",", " |");
+ }
+ };
+ }
+
+ private final boolean isList;
+ private final ConfigurationValueParser parser;
+
+ public static ConfigurationDataType toDataType(Class<? extends ConfigurationKey<?>> keyClass) {
+ if (keyClass.getSuperclass() != ConfigurationKey.class) {
+ throw new IllegalArgumentException("No direct subclass of ConfigurationKey: " + keyClass.getName());
+ }
+
+ Type type = keyClass.getGenericSuperclass();
+ if (!(type instanceof ParameterizedType)) {
+ throw new IllegalArgumentException("Missing type parameter in "+ type);
+ }
+
+ ParameterizedType parameterized = (ParameterizedType) type;
+ Type argumentType = parameterized.getActualTypeArguments()[0];
+
+ boolean isList = false;
+ if (argumentType instanceof ParameterizedType) {
+ ParameterizedType parameterizedArgument = (ParameterizedType) argumentType;
+ if (parameterizedArgument.getRawType() == List.class) {
+ isList = true;
+ argumentType = parameterizedArgument.getActualTypeArguments()[0];
+ }
+ }
+
+ if (SIMPLE_TYPES.containsKey(argumentType)) {
+ return new ConfigurationDataType(isList, SIMPLE_TYPES.get(argumentType));
+ }
+
+ if (isEnum(argumentType)) {
+ return new ConfigurationDataType(isList, enumParser(argumentType));
+ }
+
+ throw new IllegalArgumentException("Unsupported type parameter in " + type);
+ }
+
+ private ConfigurationDataType(boolean isList, ConfigurationValueParser parser) {
+ this.isList = isList;
+ this.parser = parser;
+ }
+
+ boolean isList() {
+ return isList;
+ }
+
+ ConfigurationValueParser getParser() {
+ return parser;
+ }
+
+ @Override
+ public String toString() {
+ if (isList) return "list of " + parser.description();
+ return parser.description();
+ }
+
+ private static boolean isEnum(Type argumentType) {
+ return argumentType instanceof Class && ((Class<?>) argumentType).isEnum();
+ }
+} \ No newline at end of file
diff --git a/src/core/lombok/core/configuration/ConfigurationKey.java b/src/core/lombok/core/configuration/ConfigurationKey.java
new file mode 100644
index 00000000..d46a70b0
--- /dev/null
+++ b/src/core/lombok/core/configuration/ConfigurationKey.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2013-2014 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 java.util.Collections;
+import java.util.Map;
+import java.util.TreeMap;
+import java.util.regex.Pattern;
+
+/**
+ * Describes a configuration key and its type.
+ * <p>
+ * The recommended usage is to create a type token:
+ * <pre>
+ * private static ConfigurationKey&lt;String> KEY = new ConfigurationKey&lt;String>("keyName", "description") {};
+ * </pre>
+ */
+public abstract class ConfigurationKey<T> {
+ private static final Pattern VALID_NAMES = Pattern.compile("[-_a-zA-Z][-.\\w]*(?<![-.])");
+
+ private static final TreeMap<String, ConfigurationKey<?>> registeredKeys = new TreeMap<String, ConfigurationKey<?>>(String.CASE_INSENSITIVE_ORDER);
+ private static Map<String, ConfigurationKey<?>> copy;
+
+ private final String keyName;
+ private final String description;
+ private final ConfigurationDataType type;
+
+ public ConfigurationKey(String keyName, String description) {
+ this.keyName = checkName(keyName);
+ @SuppressWarnings("unchecked")
+ ConfigurationDataType type = ConfigurationDataType.toDataType((Class<? extends ConfigurationKey<?>>)getClass());
+ this.type = type;
+ this.description = description;
+ registerKey(keyName, this);
+ }
+
+ public final String getKeyName() {
+ return keyName;
+ }
+
+ public final String getDescription() {
+ return description;
+ }
+
+ public final ConfigurationDataType getType() {
+ return type;
+ }
+
+ @Override public String toString() {
+ return keyName + " (" + type + "): " + description;
+ }
+
+ private static String checkName(String keyName) {
+ if (keyName == null) throw new NullPointerException("keyName");
+ if (!VALID_NAMES.matcher(keyName).matches()) throw new IllegalArgumentException("Invalid keyName: " + keyName);
+ return keyName;
+ }
+
+ /**
+ * Returns a copy of the currently registered keys.
+ */
+ @SuppressWarnings("unchecked")
+ public static Map<String, ConfigurationKey<?>> registeredKeys() {
+ synchronized (registeredKeys) {
+ if (copy == null) copy = Collections.unmodifiableMap((Map<String, ConfigurationKey<?>>) registeredKeys.clone());
+ return copy;
+ }
+ }
+
+ private static void registerKey(String keyName, ConfigurationKey<?> key) {
+ synchronized (registeredKeys) {
+ if (registeredKeys.containsKey(keyName)) throw new IllegalArgumentException("Key '" + keyName + "' already registered");
+ registeredKeys.put(keyName, key);
+ copy = null;
+ }
+ }
+} \ No newline at end of file
diff --git a/src/core/lombok/core/configuration/ConfigurationKeysLoader.java b/src/core/lombok/core/configuration/ConfigurationKeysLoader.java
new file mode 100644
index 00000000..4e6e4fb1
--- /dev/null
+++ b/src/core/lombok/core/configuration/ConfigurationKeysLoader.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2014 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 java.io.IOException;
+import java.util.Iterator;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import lombok.ConfigurationKeys;
+import lombok.core.SpiLoadUtil;
+
+public interface ConfigurationKeysLoader {
+ public class LoaderLoader {
+ private static final AtomicBoolean alreadyLoaded = new AtomicBoolean(false);
+ private LoaderLoader() {}
+
+ public static void loadAllConfigurationKeys() {
+ if (alreadyLoaded.get()) return;
+
+ try {
+ Class.forName(ConfigurationKeys.class.getName());
+ } catch (Throwable ignore) {}
+
+ try {
+ Iterator<ConfigurationKeysLoader> iterator = SpiLoadUtil.findServices(ConfigurationKeysLoader.class, ConfigurationKeysLoader.class.getClassLoader()).iterator();
+ while (iterator.hasNext()) {
+ try {
+ iterator.next();
+ } catch (Exception ignore) {}
+ }
+ } catch (IOException e) {
+ throw new RuntimeException("Can't load config keys; services file issue.", e);
+ } finally {
+ alreadyLoaded.set(true);
+ }
+ }
+ }
+}
diff --git a/src/core/lombok/core/configuration/ConfigurationParser.java b/src/core/lombok/core/configuration/ConfigurationParser.java
new file mode 100644
index 00000000..f0a9e142
--- /dev/null
+++ b/src/core/lombok/core/configuration/ConfigurationParser.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2014 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 java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class ConfigurationParser {
+ private static final Pattern LINE = Pattern.compile("(?:clear\\s+([^=]+))|(?:(\\S*?)\\s*([-+]?=)\\s*(.*?))");
+ private static final Pattern NEWLINE_FINDER = Pattern.compile("^\\s*(.*?)\\s*$", Pattern.MULTILINE);
+
+ private ConfigurationProblemReporter reporter;
+
+ public ConfigurationParser(ConfigurationProblemReporter reporter) {
+ if (reporter == null) throw new NullPointerException("reporter");
+ this.reporter = reporter;
+ }
+
+ public void parse(CharSequence content, String contentDescription, Collector collector) {
+ Map<String, ConfigurationKey<?>> registeredKeys = ConfigurationKey.registeredKeys();
+ int lineNumber = 0;
+ Matcher lineMatcher = NEWLINE_FINDER.matcher(content);
+ while (lineMatcher.find()) {
+ CharSequence line = content.subSequence(lineMatcher.start(1), lineMatcher.end(1));
+ lineNumber++;
+ if (line.length() == 0 || line.charAt(0) == '#') continue;
+
+ Matcher matcher = LINE.matcher(line);
+ if (!matcher.matches()) {
+ reporter.report(contentDescription, "Invalid line", lineNumber, line);
+ continue;
+ }
+
+ String operator = null;
+ String keyName = null;
+ String stringValue;
+ if (matcher.group(1) == null) {
+ keyName = matcher.group(2);
+ operator = matcher.group(3);
+ stringValue = matcher.group(4);
+ } else {
+ keyName = matcher.group(1);
+ operator = "clear";
+ stringValue = null;
+ }
+ ConfigurationKey<?> key = registeredKeys.get(keyName);
+ if (key == null) {
+ reporter.report(contentDescription, "Unknown key '" + keyName + "'", lineNumber, line);
+ continue;
+ }
+
+ ConfigurationDataType type = key.getType();
+ boolean listOperator = operator.equals("+=") || operator.equals("-=");
+ if (listOperator && !type.isList()) {
+ reporter.report(contentDescription, "'" + keyName + "' is not a list and doesn't support " + operator + " (only = and clear)", lineNumber, line);
+ continue;
+ }
+ if (operator.equals("=") && type.isList()) {
+ reporter.report(contentDescription, "'" + keyName + "' is a list and cannot be assigned to (use +=, -= and clear instead)", lineNumber, line);
+ continue;
+ }
+
+ Object value = null;
+ if (stringValue != null) try {
+ value = type.getParser().parse(stringValue);
+ } catch (Exception e) {
+ reporter.report(contentDescription, "Error while parsing the value for '" + keyName + "' value '" + stringValue + "' (should be " + type.getParser().exampleValue() + ")", lineNumber, line);
+ continue;
+ }
+
+ if (operator.equals("clear")) {
+ collector.clear(key, contentDescription, lineNumber);
+ } else if (operator.equals("=")) {
+ collector.set(key, value, contentDescription, lineNumber);
+ } else if (operator.equals("+=")) {
+ collector.add(key, value, contentDescription, lineNumber);
+ } else {
+ collector.remove(key, value, contentDescription, lineNumber);
+ }
+ }
+ }
+
+ public interface Collector {
+ void clear(ConfigurationKey<?> key, String contentDescription, int lineNumber);
+ void set(ConfigurationKey<?> key, Object value, String contentDescription, int lineNumber);
+ void add(ConfigurationKey<?> key, Object value, String contentDescription, int lineNumber);
+ void remove(ConfigurationKey<?> key, Object value, String contentDescription, int lineNumber);
+ }
+}
diff --git a/src/core/lombok/core/configuration/ConfigurationProblemReporter.java b/src/core/lombok/core/configuration/ConfigurationProblemReporter.java
new file mode 100644
index 00000000..5dbf99a8
--- /dev/null
+++ b/src/core/lombok/core/configuration/ConfigurationProblemReporter.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2014 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;
+
+public interface ConfigurationProblemReporter {
+ void report(String sourceDescription, String problem, int lineNumber, CharSequence line);
+
+ ConfigurationProblemReporter CONSOLE = new ConfigurationProblemReporter() {
+ @Override public void report(String sourceDescription, String problem, int lineNumber, CharSequence line) {
+ System.err.printf("%s (%s:%d)\n", problem, sourceDescription, lineNumber);
+ }
+ };
+}
diff --git a/src/core/lombok/core/configuration/ConfigurationResolver.java b/src/core/lombok/core/configuration/ConfigurationResolver.java
new file mode 100644
index 00000000..6f52fc6e
--- /dev/null
+++ b/src/core/lombok/core/configuration/ConfigurationResolver.java
@@ -0,0 +1,26 @@
+/*
+ * 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;
+
+public interface ConfigurationResolver {
+ <T> T resolve(ConfigurationKey<T> key);
+}
diff --git a/src/core/lombok/core/configuration/ConfigurationResolverFactory.java b/src/core/lombok/core/configuration/ConfigurationResolverFactory.java
new file mode 100644
index 00000000..83b58c2f
--- /dev/null
+++ b/src/core/lombok/core/configuration/ConfigurationResolverFactory.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2014 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.AST;
+
+public interface ConfigurationResolverFactory {
+ ConfigurationResolver createResolver(AST<?, ?, ?> ast);
+}
diff --git a/src/core/lombok/core/configuration/ConfigurationSource.java b/src/core/lombok/core/configuration/ConfigurationSource.java
new file mode 100644
index 00000000..4a2b5808
--- /dev/null
+++ b/src/core/lombok/core/configuration/ConfigurationSource.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2014 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;
+
+public interface ConfigurationSource {
+
+ Result resolve(ConfigurationKey<?> key);
+
+ public static final class Result {
+ private final Object value;
+ private final boolean authoritative;
+
+ public Result(Object value, boolean authoritative) {
+ this.value = value;
+ this.authoritative = authoritative;
+ }
+
+ public Object getValue() {
+ return value;
+ }
+
+ public boolean isAuthoritative() {
+ return authoritative;
+ }
+
+ @Override public String toString() {
+ return String.valueOf(value) + (authoritative ? " (set)" : " (delta)");
+ }
+ }
+
+ public static class ListModification {
+ private final Object value;
+ private final boolean added;
+
+ public ListModification(Object value, boolean added) {
+ this.value = value;
+ this.added = added;
+ }
+
+ public Object getValue() {
+ return value;
+ }
+
+ public boolean isAdded() {
+ return added;
+ }
+ }
+} \ No newline at end of file
diff --git a/src/core/lombok/core/configuration/ConfigurationValueParser.java b/src/core/lombok/core/configuration/ConfigurationValueParser.java
new file mode 100644
index 00000000..cf3bd5ab
--- /dev/null
+++ b/src/core/lombok/core/configuration/ConfigurationValueParser.java
@@ -0,0 +1,28 @@
+/*
+ * 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;
+
+interface ConfigurationValueParser {
+ Object parse(String value);
+ String description();
+ String exampleValue();
+} \ No newline at end of file
diff --git a/src/core/lombok/core/configuration/FileSystemSourceCache.java b/src/core/lombok/core/configuration/FileSystemSourceCache.java
new file mode 100644
index 00000000..03e6d338
--- /dev/null
+++ b/src/core/lombok/core/configuration/FileSystemSourceCache.java
@@ -0,0 +1,184 @@
+/*
+ * Copyright (C) 2014 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 java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.net.URI;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.TimeUnit;
+
+import lombok.ConfigurationKeys;
+import lombok.core.configuration.ConfigurationSource.Result;
+
+public class FileSystemSourceCache {
+ private static String LOMBOK_CONFIG_FILENAME = "lombok.config";
+ private static final long RECHECK_FILESYSTEM = TimeUnit.SECONDS.toMillis(2);
+ private static final long MISSING = -1;
+
+ private final ConcurrentMap<File, Content> cache = new ConcurrentHashMap<File, Content>();
+
+ public Iterable<ConfigurationSource> sourcesForJavaFile(URI javaFile, ConfigurationProblemReporter reporter) {
+ if (javaFile == null) return Collections.emptyList();
+ return sourcesForDirectory(new File(javaFile.normalize()).getParentFile(), reporter);
+ }
+
+ public Iterable<ConfigurationSource> sourcesForDirectory(URI directory, ConfigurationProblemReporter reporter) {
+ if (directory == null) return Collections.emptyList();
+ return sourcesForDirectory(new File(directory.normalize()), reporter);
+ }
+
+ private Iterable<ConfigurationSource> sourcesForDirectory(final File directory, final ConfigurationProblemReporter reporter) {
+ return new Iterable<ConfigurationSource>() {
+ @Override
+ public Iterator<ConfigurationSource> iterator() {
+ return new Iterator<ConfigurationSource>() {
+ File currentDirectory = directory;
+ ConfigurationSource next;
+ boolean stopBubbling = false;
+
+ @Override
+ public boolean hasNext() {
+ if (next != null) return true;
+ if (stopBubbling) return false;
+ next = findNext();
+ return next != null;
+ }
+
+ @Override
+ public ConfigurationSource next() {
+ if (!hasNext()) throw new NoSuchElementException();
+ ConfigurationSource result = next;
+ next = null;
+ return result;
+ }
+
+ private ConfigurationSource findNext() {
+ while (currentDirectory != null && next == null) {
+ next = getSourceForDirectory(currentDirectory, reporter);
+ currentDirectory = currentDirectory.getParentFile();
+ }
+ if (next != null) {
+ Result stop = next.resolve(ConfigurationKeys.STOP_BUBBLING);
+ stopBubbling = (stop != null && Boolean.TRUE.equals(stop.getValue()));
+ }
+ return next;
+ }
+
+ @Override
+ public void remove() {
+ throw new UnsupportedOperationException();
+ }
+ };
+ }
+ };
+ }
+
+ ConfigurationSource getSourceForDirectory(File directory, ConfigurationProblemReporter reporter) {
+ if (!directory.exists() && !directory.isDirectory()) throw new IllegalArgumentException("Not a directory: " + directory);
+ long now = System.currentTimeMillis();
+ File configFile = new File(directory, LOMBOK_CONFIG_FILENAME);
+
+ Content content = ensureContent(directory);
+ synchronized (content) {
+ if (content.lastChecked != MISSING && now - content.lastChecked < RECHECK_FILESYSTEM && getLastModified(configFile) == content.lastModified) {
+ return content.source;
+ }
+ content.lastChecked = now;
+ long previouslyModified = content.lastModified;
+ content.lastModified = getLastModified(configFile);
+ if (content.lastModified != previouslyModified) content.source = content.lastModified == MISSING ? null : parse(configFile, reporter);
+ return content.source;
+ }
+ }
+
+ private Content ensureContent(File directory) {
+ Content content = cache.get(directory);
+ if (content != null) {
+ return content;
+ }
+ cache.putIfAbsent(directory, Content.empty());
+ return cache.get(directory);
+ }
+
+ private ConfigurationSource parse(File configFile, ConfigurationProblemReporter reporter) {
+ String contentDescription = configFile.getAbsolutePath();
+ try {
+ return StringConfigurationSource.forString(fileToString(configFile), reporter, contentDescription);
+ } catch (Exception e) {
+ reporter.report(contentDescription, "Exception while reading file: " + e.getMessage(), 0, null);
+ return null;
+ }
+ }
+
+ private static final ThreadLocal<byte[]> buffers = new ThreadLocal<byte[]>() {
+ protected byte[] initialValue() {
+ return new byte[65536];
+ }
+ };
+
+ static String fileToString(File configFile) throws Exception {
+ byte[] b = buffers.get();
+ FileInputStream fis = new FileInputStream(configFile);
+ try {
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ while (true) {
+ int r = fis.read(b);
+ if (r == -1) break;
+ out.write(b, 0, r);
+ }
+ return new String(out.toByteArray(), "UTF-8");
+ } finally {
+ fis.close();
+ }
+ }
+
+ private static final long getLastModified(File file) {
+ if (!file.exists() || !file.isFile()) return MISSING;
+ return file.lastModified();
+ }
+
+ private static class Content {
+ ConfigurationSource source;
+ long lastModified;
+ long lastChecked;
+
+ private Content(ConfigurationSource source, long lastModified, long lastChecked) {
+ this.source = source;
+ this.lastModified = lastModified;
+ this.lastChecked = lastChecked;
+ }
+
+ static Content empty() {
+ return new Content(null, MISSING, MISSING);
+ }
+ }
+
+ public void reset() {
+ cache.clear();
+ }
+} \ No newline at end of file
diff --git a/src/core/lombok/core/configuration/StringConfigurationSource.java b/src/core/lombok/core/configuration/StringConfigurationSource.java
new file mode 100644
index 00000000..dd2f0319
--- /dev/null
+++ b/src/core/lombok/core/configuration/StringConfigurationSource.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2014 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 java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import lombok.core.configuration.ConfigurationParser.Collector;
+
+public class StringConfigurationSource implements ConfigurationSource {
+ private final Map<ConfigurationKey<?>, Result> values;
+
+ public static ConfigurationSource forString(CharSequence content, ConfigurationProblemReporter reporter, String contentDescription) {
+
+ final Map<ConfigurationKey<?>, Result> values = new HashMap<ConfigurationKey<?>, Result>();
+
+ new ConfigurationParser(reporter).parse(content, contentDescription, new Collector() {
+ @Override public void clear(ConfigurationKey<?> key, String contentDescription, int lineNumber) {
+ values.put(key, new Result(null, true));
+ }
+
+ @Override public void set(ConfigurationKey<?> key, Object value, String contentDescription, int lineNumber) {
+ values.put(key, new Result(value, true));
+ }
+
+ @Override public void add(ConfigurationKey<?> key, Object value, String contentDescription, int lineNumber) {
+ modifyList(key, value, true);
+ }
+
+ @Override public void remove(ConfigurationKey<?> key, Object value, String contentDescription, int lineNumber) {
+ modifyList(key, value, false);
+ }
+
+ @SuppressWarnings("unchecked")
+ private void modifyList(ConfigurationKey<?> key, Object value, boolean add) {
+ Result result = values.get(key);
+ List<ListModification> list;
+ if (result == null || result.getValue() == null) {
+ list = new ArrayList<ConfigurationSource.ListModification>();
+ values.put(key, new Result(list, result != null));
+ } else {
+ list = (List<ListModification>) result.getValue();
+ }
+ list.add(new ListModification(value, add));
+ }
+ });
+
+ return new StringConfigurationSource(values);
+ }
+
+ private StringConfigurationSource(Map<ConfigurationKey<?>, Result> values) {
+ this.values = new HashMap<ConfigurationKey<?>, Result>();
+ for (Entry<ConfigurationKey<?>, Result> entry : values.entrySet()) {
+ Result result = entry.getValue();
+ if (result.getValue() instanceof List<?>) {
+ this.values.put(entry.getKey(), new Result(Collections.unmodifiableList((List<?>) result.getValue()), result.isAuthoritative()));
+ } else {
+ this.values.put(entry.getKey(), result);
+ }
+ }
+ }
+
+ @Override
+ public Result resolve(ConfigurationKey<?> key) {
+ return values.get(key);
+ }
+}
diff --git a/src/core/lombok/core/configuration/TypeName.java b/src/core/lombok/core/configuration/TypeName.java
new file mode 100644
index 00000000..989e1b97
--- /dev/null
+++ b/src/core/lombok/core/configuration/TypeName.java
@@ -0,0 +1,47 @@
+/*
+ * 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;
+
+public final class TypeName {
+ private final String name;
+
+ private TypeName(String name) {
+ this.name = name;
+ }
+
+ public static TypeName valueOf(String name) {
+ return new TypeName(name);
+ }
+
+ @Override public boolean equals(Object obj) {
+ if (!(obj instanceof TypeName)) return false;
+ return name.equals(((TypeName) obj).name);
+ }
+
+ @Override public int hashCode() {
+ return name.hashCode();
+ }
+
+ @Override public String toString() {
+ return name;
+ }
+}
diff --git a/src/core/lombok/core/handlers/HandlerUtil.java b/src/core/lombok/core/handlers/HandlerUtil.java
index 23b8ccc7..fe2f3406 100644
--- a/src/core/lombok/core/handlers/HandlerUtil.java
+++ b/src/core/lombok/core/handlers/HandlerUtil.java
@@ -21,9 +21,38 @@
*/
package lombok.core.handlers;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.regex.Pattern;
+
+import lombok.AllArgsConstructor;
+import lombok.ConfigurationKeys;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.RequiredArgsConstructor;
+import lombok.Setter;
+import lombok.ToString;
+import lombok.Value;
+import lombok.core.AST;
+import lombok.core.AnnotationValues;
+import lombok.core.FlagUsageType;
import lombok.core.JavaIdentifiers;
import lombok.core.LombokNode;
+import lombok.core.configuration.ConfigurationKey;
+import lombok.experimental.Accessors;
+import lombok.experimental.FieldDefaults;
+import lombok.experimental.Wither;
+/**
+ * Container for static utility methods useful for some of the standard lombok handlers, regardless of
+ * target platform (e.g. useful for both javac and Eclipse lombok implementations).
+ */
public class HandlerUtil {
private HandlerUtil() {}
@@ -57,4 +86,336 @@ public class HandlerUtil {
return true;
}
+
+ public static void handleFlagUsage(LombokNode<?, ?, ?> node, ConfigurationKey<FlagUsageType> key, String featureName) {
+ FlagUsageType fut = node.getAst().readConfiguration(key);
+
+ if (fut != null) {
+ String msg = "Use of " + featureName + " is flagged according to lombok configuration.";
+ if (fut == FlagUsageType.WARNING) node.addWarning(msg);
+ else node.addError(msg);
+ }
+ }
+
+ public static void handleExperimentalFlagUsage(LombokNode<?, ?, ?> node, ConfigurationKey<FlagUsageType> key, String featureName) {
+ handleFlagUsage(node, key, featureName, ConfigurationKeys.EXPERIMENTAL_FLAG_USAGE, "any lombok.experimental feature");
+ }
+
+ public static void handleFlagUsage(LombokNode<?, ?, ?> node, ConfigurationKey<FlagUsageType> key1, String featureName1, ConfigurationKey<FlagUsageType> key2, String featureName2) {
+ FlagUsageType fut1 = node.getAst().readConfiguration(key1);
+ FlagUsageType fut2 = node.getAst().readConfiguration(key2);
+
+ FlagUsageType fut = null;
+ String featureName = null;
+ if (fut1 == FlagUsageType.ERROR) {
+ fut = fut1;
+ featureName = featureName1;
+ } else if (fut2 == FlagUsageType.ERROR) {
+ fut = fut2;
+ featureName = featureName2;
+ } else if (fut1 == FlagUsageType.WARNING) {
+ fut = fut1;
+ featureName = featureName1;
+ } else {
+ fut = fut2;
+ featureName = featureName2;
+ }
+
+ if (fut != null) {
+ String msg = "Use of " + featureName + " is flagged according to lombok configuration.";
+ if (fut == FlagUsageType.WARNING) node.addWarning(msg);
+ else node.addError(msg);
+ }
+ }
+
+ public static boolean shouldReturnThis0(AnnotationValues<Accessors> accessors, AST<?, ?, ?> ast) {
+ boolean chainForced = accessors.isExplicit("chain");
+ boolean fluentForced = accessors.isExplicit("fluent");
+ Accessors instance = accessors.getInstance();
+
+ boolean chain = instance.chain();
+ boolean fluent = instance.fluent();
+
+ if (chainForced) return chain;
+
+ if (!chainForced) {
+ Boolean chainConfig = ast.readConfiguration(ConfigurationKeys.ACCESSORS_CHAIN);
+ if (chainConfig != null) return chainConfig;
+ }
+
+ if (!fluentForced) {
+ Boolean fluentConfig = ast.readConfiguration(ConfigurationKeys.ACCESSORS_FLUENT);
+ if (fluentConfig != null) fluent = fluentConfig;
+ }
+
+ return chain || fluent;
+ }
+
+ @SuppressWarnings({"all", "unchecked", "deprecation"})
+ public static final List<Class<? extends java.lang.annotation.Annotation>> INVALID_ON_BUILDERS = Collections.unmodifiableList(
+ Arrays.<Class<? extends java.lang.annotation.Annotation>>asList(
+ Getter.class, Setter.class, Wither.class, ToString.class, EqualsAndHashCode.class,
+ RequiredArgsConstructor.class, AllArgsConstructor.class, NoArgsConstructor.class,
+ Data.class, Value.class, lombok.experimental.Value.class, FieldDefaults.class));
+
+ /**
+ * Given the name of a field, return the 'base name' of that field. For example, {@code fFoobar} becomes {@code foobar} if {@code f} is in the prefix list.
+ * For prefixes that end in a letter character, the next character must be a non-lowercase character (i.e. {@code hashCode} is not {@code ashCode} even if
+ * {@code h} is in the prefix list, but {@code hAshcode} would become {@code ashCode}). The first prefix that matches is used. If the prefix list is empty,
+ * or the empty string is in the prefix list and no prefix before it matches, the fieldName will be returned verbatim.
+ *
+ * If no prefix matches and the empty string is not in the prefix list and the prefix list is not empty, {@code null} is returned.
+ *
+ * @param fieldName The full name of a field.
+ * @param prefixes A list of prefixes, usually provided by the {@code Accessors} settings annotation, listing field prefixes.
+ * @return The base name of the field.
+ */
+ public static CharSequence removePrefix(CharSequence fieldName, List<String> prefixes) {
+ if (prefixes == null || prefixes.isEmpty()) return fieldName;
+
+ fieldName = fieldName.toString();
+
+ outer:
+ for (String prefix : prefixes) {
+ if (prefix.length() == 0) return fieldName;
+ if (fieldName.length() <= prefix.length()) continue outer;
+ for (int i = 0; i < prefix.length(); i++) {
+ if (fieldName.charAt(i) != prefix.charAt(i)) continue outer;
+ }
+ char followupChar = fieldName.charAt(prefix.length());
+ // if prefix is a letter then follow up letter needs to not be lowercase, i.e. 'foo' is not a match
+ // as field named 'oo' with prefix 'f', but 'fOo' would be.
+ if (Character.isLetter(prefix.charAt(prefix.length() - 1)) &&
+ Character.isLowerCase(followupChar)) continue outer;
+ return "" + Character.toLowerCase(followupChar) + fieldName.subSequence(prefix.length() + 1, fieldName.length());
+ }
+
+ return null;
+ }
+
+ /* NB: 'notnull' is not part of the pattern because there are lots of @NotNull annotations out there that are crappily named and actually mean
+ something else, such as 'this field must not be null _when saved to the db_ but its perfectly okay to start out as such, and a no-args
+ constructor and the implied starts-out-as-null state that goes with it is in fact mandatory' which happens with javax.validation.constraints.NotNull.
+ Various problems with spring have also been reported. See issue #287, issue #271, and issue #43. */
+
+ /** Matches the simple part of any annotation that lombok considers as indicative of NonNull status. */
+ public static final Pattern NON_NULL_PATTERN = Pattern.compile("^(?:nonnull)$", Pattern.CASE_INSENSITIVE);
+
+ /** Matches the simple part of any annotation that lombok considers as indicative of Nullable status. */
+ public static final Pattern NULLABLE_PATTERN = Pattern.compile("^(?:nullable|checkfornull)$", Pattern.CASE_INSENSITIVE);
+
+ /**
+ * Generates a getter name from a given field name.
+ *
+ * Strategy:
+ * <ul>
+ * <li>Reduce the field's name to its base name by stripping off any prefix (from {@code Accessors}). If the field name does not fit
+ * the prefix list, this method immediately returns {@code null}.</li>
+ * <li>If {@code Accessors} has {@code fluent=true}, then return the basename.</li>
+ * <li>Pick a prefix. 'get' normally, but 'is' if {@code isBoolean} is true.</li>
+ * <li>Only if {@code isBoolean} is true: Check if the field starts with {@code is} followed by a non-lowercase character. If so, return the field name verbatim.</li>
+ * <li>Check if the first character of the field is lowercase. If so, check if the second character
+ * exists and is title or upper case. If so, uppercase the first character. If not, titlecase the first character.</li>
+ * <li>Return the prefix plus the possibly title/uppercased first character, and the rest of the field name.</li>
+ * </ul>
+ *
+ * @param accessors Accessors configuration.
+ * @param fieldName the name of the field.
+ * @param isBoolean if the field is of type 'boolean'. For fields of type {@code java.lang.Boolean}, you should provide {@code false}.
+ * @return The getter name for this field, or {@code null} if this field does not fit expected patterns and therefore cannot be turned into a getter name.
+ */
+ public static String toGetterName(AST<?, ?, ?> ast, AnnotationValues<Accessors> accessors, CharSequence fieldName, boolean isBoolean) {
+ return toAccessorName(ast, accessors, fieldName, isBoolean, "is", "get", true);
+ }
+
+ /**
+ * Generates a setter name from a given field name.
+ *
+ * Strategy:
+ * <ul>
+ * <li>Reduce the field's name to its base name by stripping off any prefix (from {@code Accessors}). If the field name does not fit
+ * the prefix list, this method immediately returns {@code null}.</li>
+ * <li>If {@code Accessors} has {@code fluent=true}, then return the basename.</li>
+ * <li>Only if {@code isBoolean} is true: Check if the field starts with {@code is} followed by a non-lowercase character.
+ * If so, replace {@code is} with {@code set} and return that.</li>
+ * <li>Check if the first character of the field is lowercase. If so, check if the second character
+ * exists and is title or upper case. If so, uppercase the first character. If not, titlecase the first character.</li>
+ * <li>Return {@code "set"} plus the possibly title/uppercased first character, and the rest of the field name.</li>
+ * </ul>
+ *
+ * @param accessors Accessors configuration.
+ * @param fieldName the name of the field.
+ * @param isBoolean if the field is of type 'boolean'. For fields of type {@code java.lang.Boolean}, you should provide {@code false}.
+ * @return The setter name for this field, or {@code null} if this field does not fit expected patterns and therefore cannot be turned into a getter name.
+ */
+ public static String toSetterName(AST<?, ?, ?> ast, AnnotationValues<Accessors> accessors, CharSequence fieldName, boolean isBoolean) {
+ return toAccessorName(ast, accessors, fieldName, isBoolean, "set", "set", true);
+ }
+
+ /**
+ * Generates a wither name from a given field name.
+ *
+ * Strategy:
+ * <ul>
+ * <li>Reduce the field's name to its base name by stripping off any prefix (from {@code Accessors}). If the field name does not fit
+ * the prefix list, this method immediately returns {@code null}.</li>
+ * <li>Only if {@code isBoolean} is true: Check if the field starts with {@code is} followed by a non-lowercase character.
+ * If so, replace {@code is} with {@code with} and return that.</li>
+ * <li>Check if the first character of the field is lowercase. If so, check if the second character
+ * exists and is title or upper case. If so, uppercase the first character. If not, titlecase the first character.</li>
+ * <li>Return {@code "with"} plus the possibly title/uppercased first character, and the rest of the field name.</li>
+ * </ul>
+ *
+ * @param accessors Accessors configuration.
+ * @param fieldName the name of the field.
+ * @param isBoolean if the field is of type 'boolean'. For fields of type {@code java.lang.Boolean}, you should provide {@code false}.
+ * @return The wither name for this field, or {@code null} if this field does not fit expected patterns and therefore cannot be turned into a getter name.
+ */
+ public static String toWitherName(AST<?, ?, ?> ast, AnnotationValues<Accessors> accessors, CharSequence fieldName, boolean isBoolean) {
+ return toAccessorName(ast, accessors, fieldName, isBoolean, "with", "with", false);
+ }
+
+ private static String toAccessorName(AST<?, ?, ?> ast, AnnotationValues<Accessors> accessors, CharSequence fieldName, boolean isBoolean,
+ String booleanPrefix, String normalPrefix, boolean adhereToFluent) {
+
+ fieldName = fieldName.toString();
+ if (fieldName.length() == 0) return null;
+
+ boolean explicitPrefix = accessors != null && accessors.isExplicit("prefix");
+// System.out.printf("accessors: %s actual expr: %s val: %s\n", accessors, accessors != null ? accessors.getActualExpression("prefix") : "(null)", accessors == null ? "(null)" : Arrays.toString(accessors.getInstance().prefix()));
+ boolean explicitFluent = accessors != null && accessors.isExplicit("fluent");
+
+ Accessors ac = (explicitPrefix || explicitFluent) ? accessors.getInstance() : null;
+
+ List<String> prefix = explicitPrefix ? Arrays.asList(ac.prefix()) : ast.readConfiguration(ConfigurationKeys.ACCESSORS_PREFIX);
+ boolean fluent = explicitFluent ? ac.fluent() : Boolean.TRUE.equals(ast.readConfiguration(ConfigurationKeys.ACCESSORS_FLUENT));
+
+ fieldName = removePrefix(fieldName, prefix);
+ if (fieldName == null) return null;
+
+ String fName = fieldName.toString();
+ if (adhereToFluent && fluent) return fName;
+
+ if (isBoolean && fName.startsWith("is") && fieldName.length() > 2 && !Character.isLowerCase(fieldName.charAt(2))) {
+ // The field is for example named 'isRunning'.
+ return booleanPrefix + fName.substring(2);
+ }
+
+ return buildName(isBoolean ? booleanPrefix : normalPrefix, fName);
+ }
+
+ /**
+ * 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 accessors Accessors configuration.
+ * @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(AST<?, ?, ?> ast, AnnotationValues<Accessors> accessors, CharSequence fieldName, boolean isBoolean) {
+ return toAllAccessorNames(ast, accessors, fieldName, isBoolean, "is", "get", true);
+ }
+
+ /**
+ * 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 accessors Accessors configuration.
+ * @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(AST<?, ?, ?> ast, AnnotationValues<Accessors> accessors, CharSequence fieldName, boolean isBoolean) {
+ return toAllAccessorNames(ast, accessors, fieldName, isBoolean, "set", "set", true);
+ }
+
+ /**
+ * Returns all names of methods that would represent the wither for a field with the provided name.
+ *
+ * For example if {@code isBoolean} is true, then a field named {@code isRunning} would produce:<br />
+ * {@code [withRunning, withIsRunning]}
+ *
+ * @param accessors Accessors configuration.
+ * @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> toAllWitherNames(AST<?, ?, ?> ast, AnnotationValues<Accessors> accessors, CharSequence fieldName, boolean isBoolean) {
+ return toAllAccessorNames(ast, accessors, fieldName, isBoolean, "with", "with", false);
+ }
+
+ private static List<String> toAllAccessorNames(AST<?, ?, ?> ast, AnnotationValues<Accessors> accessors, CharSequence fieldName, boolean isBoolean,
+ String booleanPrefix, String normalPrefix, boolean adhereToFluent) {
+
+ if (!isBoolean) {
+ String accessorName = toAccessorName(ast, accessors, fieldName, false, booleanPrefix, normalPrefix, adhereToFluent);
+ return (accessorName == null) ? Collections.<String>emptyList() : Collections.singletonList(accessorName);
+ }
+
+ boolean explicitPrefix = accessors != null && accessors.isExplicit("prefix");
+ boolean explicitFluent = accessors != null && accessors.isExplicit("fluent");
+
+ Accessors ac = (explicitPrefix || explicitFluent) ? accessors.getInstance() : null;
+
+ List<String> prefix = explicitPrefix ? Arrays.asList(ac.prefix()) : ast.readConfiguration(ConfigurationKeys.ACCESSORS_PREFIX);
+ boolean fluent = explicitFluent ? ac.fluent() : Boolean.TRUE.equals(ast.readConfiguration(ConfigurationKeys.ACCESSORS_FLUENT));
+
+ fieldName = removePrefix(fieldName, prefix);
+ if (fieldName == null) return Collections.emptyList();
+
+ List<String> baseNames = toBaseNames(fieldName, isBoolean, fluent);
+
+ Set<String> names = new HashSet<String>();
+ for (String baseName : baseNames) {
+ if (adhereToFluent && fluent) {
+ names.add(baseName);
+ } else {
+ names.add(buildName(normalPrefix, baseName));
+ if (!normalPrefix.equals(booleanPrefix)) names.add(buildName(booleanPrefix, baseName));
+ }
+ }
+
+ return new ArrayList<String>(names);
+
+ }
+
+ private static List<String> toBaseNames(CharSequence fieldName, boolean isBoolean, boolean fluent) {
+ List<String> baseNames = new ArrayList<String>();
+ baseNames.add(fieldName.toString());
+
+ // isPrefix = field is called something like 'isRunning', so 'running' could also be the fieldname.
+ String fName = fieldName.toString();
+ if (fName.startsWith("is") && fName.length() > 2 && !Character.isLowerCase(fName.charAt(2))) {
+ String baseName = fName.substring(2);
+ if (fluent) {
+ baseNames.add("" + Character.toLowerCase(baseName.charAt(0)) + baseName.substring(1));
+ } else {
+ baseNames.add(baseName);
+ }
+ }
+
+ return baseNames;
+ }
+
+ /**
+ * @param prefix Something like {@code get} or {@code set} or {@code is}.
+ * @param suffix Something like {@code running}.
+ * @return prefix + smartly title-cased suffix. For example, {@code setRunning}.
+ */
+ private static String buildName(String prefix, String suffix) {
+ if (suffix.length() == 0) return prefix;
+ if (prefix.length() == 0) return suffix;
+
+ char first = suffix.charAt(0);
+ if (Character.isLowerCase(first)) {
+ boolean useUpperCase = suffix.length() > 2 &&
+ (Character.isTitleCase(suffix.charAt(1)) || Character.isUpperCase(suffix.charAt(1)));
+ suffix = String.format("%s%s",
+ useUpperCase ? Character.toUpperCase(first) : Character.toTitleCase(first),
+ suffix.subSequence(1, suffix.length()));
+ }
+ return String.format("%s%s", prefix, suffix);
+ }
}
diff --git a/src/core/lombok/eclipse/EclipseAST.java b/src/core/lombok/eclipse/EclipseAST.java
index 370b40fc..45551d1c 100644
--- a/src/core/lombok/eclipse/EclipseAST.java
+++ b/src/core/lombok/eclipse/EclipseAST.java
@@ -21,10 +21,11 @@
*/
package lombok.eclipse;
+import java.io.File;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
+import java.net.URI;
import java.util.ArrayList;
-import org.eclipse.jdt.internal.compiler.CompilationResult;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
@@ -33,6 +34,9 @@ import lombok.Lombok;
import lombok.core.AST;
import lombok.core.LombokImmutableList;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.jdt.internal.compiler.CompilationResult;
import org.eclipse.jdt.internal.compiler.ast.ASTNode;
import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
import org.eclipse.jdt.internal.compiler.ast.Annotation;
@@ -64,6 +68,27 @@ public class EclipseAST extends AST<EclipseAST, EclipseNode, ASTNode> {
clearChanged();
}
+ private static volatile boolean skipEclipseWorkspaceBasedFileResolver = false;
+ public URI getAbsoluteFileLocation() {
+ if (!skipEclipseWorkspaceBasedFileResolver) {
+ try {
+ return EclipseWorkspaceBasedFileResolver.resolve(getFileName());
+ } catch (NoClassDefFoundError e) {
+ skipEclipseWorkspaceBasedFileResolver = true;
+ }
+ }
+
+ // Our fancy workspace based source file to absolute disk location algorithm only works in a fully fledged eclipse.
+ // This fallback works when using 'ecj', which has a much simpler project/path system. For example, no 'linked' resources.
+ return new File(getFileName()).getAbsoluteFile().toURI();
+ }
+
+ private static class EclipseWorkspaceBasedFileResolver {
+ public static URI resolve(String path) {
+ return ResourcesPlugin.getWorkspace().getRoot().getFile(new Path(path)).getLocationURI();
+ }
+ }
+
private static String packageDeclaration(CompilationUnitDeclaration cud) {
ImportReference pkg = cud.currentPackage;
return pkg == null ? null : Eclipse.toQualifiedName(pkg.getImportName());
diff --git a/src/core/lombok/eclipse/HandlerLibrary.java b/src/core/lombok/eclipse/HandlerLibrary.java
index 242e923c..ad9c87b9 100644
--- a/src/core/lombok/eclipse/HandlerLibrary.java
+++ b/src/core/lombok/eclipse/HandlerLibrary.java
@@ -38,6 +38,7 @@ import java.util.WeakHashMap;
import lombok.Lombok;
import lombok.core.AnnotationValues;
import lombok.core.AnnotationValues.AnnotationValueDecodeFail;
+import lombok.core.configuration.ConfigurationKeysLoader;
import lombok.core.HandlerPriority;
import lombok.core.SpiLoadUtil;
import lombok.core.TypeLibrary;
@@ -58,7 +59,9 @@ public class HandlerLibrary {
* Creates a new HandlerLibrary. Errors will be reported to the Eclipse Error log.
* You probably want to use {@link #load()} instead.
*/
- public HandlerLibrary() {}
+ public HandlerLibrary() {
+ ConfigurationKeysLoader.LoaderLoader.loadAllConfigurationKeys();
+ }
private TypeLibrary typeLibrary = new TypeLibrary();
diff --git a/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java b/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java
index fbad53d4..94fdffad 100644
--- a/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java
+++ b/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java
@@ -22,7 +22,7 @@
package lombok.eclipse.handlers;
import static lombok.eclipse.Eclipse.*;
-import static lombok.core.TransformationsUtil.*;
+import static lombok.core.handlers.HandlerUtil.*;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
@@ -38,14 +38,15 @@ import java.util.Map;
import java.util.WeakHashMap;
import lombok.AccessLevel;
+import lombok.ConfigurationKeys;
import lombok.Data;
import lombok.Getter;
import lombok.Lombok;
import lombok.core.AST.Kind;
import lombok.core.AnnotationValues;
import lombok.core.AnnotationValues.AnnotationValue;
-import lombok.core.TransformationsUtil;
import lombok.core.TypeResolver;
+import lombok.core.handlers.HandlerUtil;
import lombok.eclipse.EclipseAST;
import lombok.eclipse.EclipseNode;
import lombok.experimental.Accessors;
@@ -1043,7 +1044,7 @@ public class EclipseHandlerUtil {
* Convenient wrapper around {@link TransformationsUtil#toAllGetterNames(lombok.core.AnnotationValues, CharSequence, boolean)}.
*/
public static List<String> toAllGetterNames(EclipseNode field, boolean isBoolean) {
- return TransformationsUtil.toAllGetterNames(getAccessorsForField(field), field.getName(), isBoolean);
+ return HandlerUtil.toAllGetterNames(field.getAst(), getAccessorsForField(field), field.getName(), isBoolean);
}
/**
@@ -1052,7 +1053,7 @@ public class EclipseHandlerUtil {
* Convenient wrapper around {@link TransformationsUtil#toGetterName(lombok.core.AnnotationValues, CharSequence, boolean)}.
*/
public static String toGetterName(EclipseNode field, boolean isBoolean) {
- return TransformationsUtil.toGetterName(getAccessorsForField(field), field.getName(), isBoolean);
+ return HandlerUtil.toGetterName(field.getAst(), getAccessorsForField(field), field.getName(), isBoolean);
}
/**
@@ -1060,7 +1061,7 @@ public class EclipseHandlerUtil {
* Convenient wrapper around {@link TransformationsUtil#toAllSetterNames(lombok.core.AnnotationValues, CharSequence, boolean)}.
*/
public static java.util.List<String> toAllSetterNames(EclipseNode field, boolean isBoolean) {
- return TransformationsUtil.toAllSetterNames(getAccessorsForField(field), field.getName(), isBoolean);
+ return HandlerUtil.toAllSetterNames(field.getAst(), getAccessorsForField(field), field.getName(), isBoolean);
}
/**
@@ -1069,7 +1070,7 @@ public class EclipseHandlerUtil {
* Convenient wrapper around {@link TransformationsUtil#toSetterName(lombok.core.AnnotationValues, CharSequence, boolean)}.
*/
public static String toSetterName(EclipseNode field, boolean isBoolean) {
- return TransformationsUtil.toSetterName(getAccessorsForField(field), field.getName(), isBoolean);
+ return HandlerUtil.toSetterName(field.getAst(), getAccessorsForField(field), field.getName(), isBoolean);
}
/**
@@ -1077,7 +1078,7 @@ public class EclipseHandlerUtil {
* Convenient wrapper around {@link TransformationsUtil#toAllWitherNames(lombok.core.AnnotationValues, CharSequence, boolean)}.
*/
public static java.util.List<String> toAllWitherNames(EclipseNode field, boolean isBoolean) {
- return TransformationsUtil.toAllWitherNames(getAccessorsForField(field), field.getName(), isBoolean);
+ return HandlerUtil.toAllWitherNames(field.getAst(), getAccessorsForField(field), field.getName(), isBoolean);
}
/**
@@ -1086,19 +1087,17 @@ public class EclipseHandlerUtil {
* Convenient wrapper around {@link TransformationsUtil#toWitherName(lombok.core.AnnotationValues, CharSequence, boolean)}.
*/
public static String toWitherName(EclipseNode field, boolean isBoolean) {
- return TransformationsUtil.toWitherName(getAccessorsForField(field), field.getName(), isBoolean);
+ return HandlerUtil.toWitherName(field.getAst(), getAccessorsForField(field), field.getName(), isBoolean);
}
/**
* When generating a setter, the setter either returns void (beanspec) or Self (fluent).
- * This method scans for the {@code Accessors} annotation to figure that out.
+ * This method scans for the {@code Accessors} annotation and associated config properties to figure that out.
*/
public static boolean shouldReturnThis(EclipseNode field) {
if ((((FieldDeclaration) field.get()).modifiers & ClassFileConstants.AccStatic) != 0) return false;
AnnotationValues<Accessors> accessors = EclipseHandlerUtil.getAccessorsForField(field);
- boolean forced = (accessors.getActualExpression("chain") != null);
- Accessors instance = accessors.getInstance();
- return instance.chain() || (instance.fluent() && !forced);
+ return shouldReturnThis0(accessors, field.getAst());
}
/**
@@ -1126,10 +1125,11 @@ public class EclipseHandlerUtil {
}
public static char[] removePrefixFromField(EclipseNode field) {
- String[] prefixes = null;
+ List<String> prefixes = null;
for (EclipseNode node : field.down()) {
if (annotationTypeMatches(Accessors.class, node)) {
- prefixes = createAnnotation(Accessors.class, node).getInstance().prefix();
+ AnnotationValues<Accessors> ann = createAnnotation(Accessors.class, node);
+ if (ann.isExplicit("prefix")) prefixes = Arrays.asList(ann.getInstance().prefix());
break;
}
}
@@ -1140,7 +1140,8 @@ public class EclipseHandlerUtil {
while (current != null) {
for (EclipseNode node : current.down()) {
if (annotationTypeMatches(Accessors.class, node)) {
- prefixes = createAnnotation(Accessors.class, node).getInstance().prefix();
+ AnnotationValues<Accessors> ann = createAnnotation(Accessors.class, node);
+ if (ann.isExplicit("prefix")) prefixes = Arrays.asList(ann.getInstance().prefix());
break outer;
}
}
@@ -1148,8 +1149,9 @@ public class EclipseHandlerUtil {
}
}
- if (prefixes != null && prefixes.length > 0) {
- CharSequence newName = TransformationsUtil.removePrefix(field.getName(), prefixes);
+ if (prefixes == null) prefixes = field.getAst().readConfiguration(ConfigurationKeys.ACCESSORS_PREFIX);
+ if (!prefixes.isEmpty()) {
+ CharSequence newName = removePrefix(field.getName(), prefixes);
if (newName != null) return newName.toString().toCharArray();
}
diff --git a/src/core/lombok/eclipse/handlers/HandleAccessors.java b/src/core/lombok/eclipse/handlers/HandleAccessors.java
new file mode 100644
index 00000000..864ff50b
--- /dev/null
+++ b/src/core/lombok/eclipse/handlers/HandleAccessors.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2014 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.eclipse.handlers;
+
+import static lombok.core.handlers.HandlerUtil.handleExperimentalFlagUsage;
+import lombok.ConfigurationKeys;
+import lombok.core.AnnotationValues;
+import lombok.core.HandlerPriority;
+import lombok.eclipse.EclipseAnnotationHandler;
+import lombok.eclipse.EclipseNode;
+import lombok.experimental.Accessors;
+
+import org.eclipse.jdt.internal.compiler.ast.Annotation;
+import org.mangosdk.spi.ProviderFor;
+
+@ProviderFor(EclipseAnnotationHandler.class)
+@HandlerPriority(65536)
+public class HandleAccessors extends EclipseAnnotationHandler<Accessors> {
+ @Override public void handle(AnnotationValues<Accessors> annotation, Annotation ast, EclipseNode annotationNode) {
+ // Accessors itself is handled by HandleGetter/Setter; this is just to ensure that usages are flagged if requested.
+
+ handleExperimentalFlagUsage(annotationNode, ConfigurationKeys.ACCESSORS_FLAG_USAGE, "@Accessors");
+ }
+}
diff --git a/src/core/lombok/eclipse/handlers/HandleBuilder.java b/src/core/lombok/eclipse/handlers/HandleBuilder.java
index ea282b3b..12b16934 100644
--- a/src/core/lombok/eclipse/handlers/HandleBuilder.java
+++ b/src/core/lombok/eclipse/handlers/HandleBuilder.java
@@ -56,10 +56,10 @@ import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
import org.mangosdk.spi.ProviderFor;
import lombok.AccessLevel;
+import lombok.ConfigurationKeys;
import lombok.core.AST.Kind;
import lombok.core.AnnotationValues;
import lombok.core.HandlerPriority;
-import lombok.core.TransformationsUtil;
import lombok.eclipse.Eclipse;
import lombok.eclipse.EclipseAnnotationHandler;
import lombok.eclipse.EclipseNode;
@@ -71,6 +71,8 @@ import lombok.experimental.NonFinal;
@HandlerPriority(-1024) //-2^10; to ensure we've picked up @FieldDefault's changes (-2048) but @Value hasn't removed itself yet (-512), so that we can error on presence of it on the builder classes.
public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
@Override public void handle(AnnotationValues<Builder> annotation, Annotation ast, EclipseNode annotationNode) {
+ handleExperimentalFlagUsage(annotationNode, ConfigurationKeys.BUILDER_FLAG_USAGE, "@Builder");
+
long p = (long) ast.sourceStart << 32 | ast.sourceEnd;
Builder builderInstance = annotation.getInstance();
@@ -347,7 +349,7 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
}
boolean isBoolean = isBoolean(fd.type);
- String setterName = fluent ? fieldNode.getName() : TransformationsUtil.toSetterName(null, fieldNode.getName(), isBoolean);
+ String setterName = fluent ? fieldNode.getName() : toSetterName(builderType.getAst(), null, fieldNode.getName(), isBoolean);
return HandleSetter.createSetter(td, fieldNode, setterName, chain, ClassFileConstants.AccPublic,
source, Collections.<Annotation>emptyList(), Collections.<Annotation>emptyList());
diff --git a/src/core/lombok/eclipse/handlers/HandleCleanup.java b/src/core/lombok/eclipse/handlers/HandleCleanup.java
index b8ea1669..dde7cd08 100644
--- a/src/core/lombok/eclipse/handlers/HandleCleanup.java
+++ b/src/core/lombok/eclipse/handlers/HandleCleanup.java
@@ -21,11 +21,13 @@
*/
package lombok.eclipse.handlers;
+import static lombok.core.handlers.HandlerUtil.*;
import static lombok.eclipse.handlers.EclipseHandlerUtil.*;
import java.util.Arrays;
import lombok.Cleanup;
+import lombok.ConfigurationKeys;
import lombok.core.AnnotationValues;
import lombok.core.AST.Kind;
import lombok.eclipse.EclipseAnnotationHandler;
@@ -58,6 +60,8 @@ import org.mangosdk.spi.ProviderFor;
@ProviderFor(EclipseAnnotationHandler.class)
public class HandleCleanup extends EclipseAnnotationHandler<Cleanup> {
public void handle(AnnotationValues<Cleanup> annotation, Annotation ast, EclipseNode annotationNode) {
+ handleFlagUsage(annotationNode, ConfigurationKeys.CLEANUP_FLAG_USAGE, "@Cleanup");
+
String cleanupName = annotation.getInstance().value();
if (cleanupName.length() == 0) {
annotationNode.addError("cleanupName cannot be the empty string.");
diff --git a/src/core/lombok/eclipse/handlers/HandleConstructor.java b/src/core/lombok/eclipse/handlers/HandleConstructor.java
index d86aadee..6b7df349 100644
--- a/src/core/lombok/eclipse/handlers/HandleConstructor.java
+++ b/src/core/lombok/eclipse/handlers/HandleConstructor.java
@@ -21,6 +21,7 @@
*/
package lombok.eclipse.handlers;
+import static lombok.core.handlers.HandlerUtil.*;
import static lombok.eclipse.Eclipse.*;
import static lombok.eclipse.handlers.EclipseHandlerUtil.*;
@@ -32,11 +33,11 @@ import java.util.List;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
+import lombok.ConfigurationKeys;
import lombok.NoArgsConstructor;
import lombok.RequiredArgsConstructor;
import lombok.core.AST.Kind;
import lombok.core.AnnotationValues;
-import lombok.core.TransformationsUtil;
import lombok.eclipse.EclipseAnnotationHandler;
import lombok.eclipse.EclipseNode;
import lombok.experimental.Builder;
@@ -69,6 +70,8 @@ public class HandleConstructor {
@ProviderFor(EclipseAnnotationHandler.class)
public static class HandleNoArgsConstructor extends EclipseAnnotationHandler<NoArgsConstructor> {
@Override public void handle(AnnotationValues<NoArgsConstructor> annotation, Annotation ast, EclipseNode annotationNode) {
+ handleFlagUsage(annotationNode, ConfigurationKeys.NO_ARGS_CONSTRUCTOR_FLAG_USAGE, "@NoArgsConstructor", ConfigurationKeys.ANY_CONSTRUCTOR_FLAG_USAGE, "any @xArgsConstructor");
+
EclipseNode typeNode = annotationNode.up();
if (!checkLegality(typeNode, annotationNode, NoArgsConstructor.class.getSimpleName())) return;
NoArgsConstructor ann = annotation.getInstance();
@@ -86,6 +89,8 @@ public class HandleConstructor {
@ProviderFor(EclipseAnnotationHandler.class)
public static class HandleRequiredArgsConstructor extends EclipseAnnotationHandler<RequiredArgsConstructor> {
@Override public void handle(AnnotationValues<RequiredArgsConstructor> annotation, Annotation ast, EclipseNode annotationNode) {
+ handleFlagUsage(annotationNode, ConfigurationKeys.REQUIRED_ARGS_CONSTRUCTOR_FLAG_USAGE, "@RequiredArgsConstructor", ConfigurationKeys.ANY_CONSTRUCTOR_FLAG_USAGE, "any @xArgsConstructor");
+
EclipseNode typeNode = annotationNode.up();
if (!checkLegality(typeNode, annotationNode, RequiredArgsConstructor.class.getSimpleName())) return;
RequiredArgsConstructor ann = annotation.getInstance();
@@ -108,7 +113,7 @@ public class HandleConstructor {
FieldDeclaration fieldDecl = (FieldDeclaration) child.get();
if (!filterField(fieldDecl)) continue;
boolean isFinal = (fieldDecl.modifiers & ClassFileConstants.AccFinal) != 0;
- boolean isNonNull = findAnnotations(fieldDecl, TransformationsUtil.NON_NULL_PATTERN).length != 0;
+ boolean isNonNull = findAnnotations(fieldDecl, NON_NULL_PATTERN).length != 0;
if ((isFinal || isNonNull) && fieldDecl.initialization == null) fields.add(child);
}
return fields;
@@ -132,6 +137,8 @@ public class HandleConstructor {
@ProviderFor(EclipseAnnotationHandler.class)
public static class HandleAllArgsConstructor extends EclipseAnnotationHandler<AllArgsConstructor> {
@Override public void handle(AnnotationValues<AllArgsConstructor> annotation, Annotation ast, EclipseNode annotationNode) {
+ handleFlagUsage(annotationNode, ConfigurationKeys.ALL_ARGS_CONSTRUCTOR_FLAG_USAGE, "@AllArgsConstructor", ConfigurationKeys.ANY_CONSTRUCTOR_FLAG_USAGE, "any @xArgsConstructor");
+
EclipseNode typeNode = annotationNode.up();
if (!checkLegality(typeNode, annotationNode, AllArgsConstructor.class.getSimpleName())) return;
AllArgsConstructor ann = annotation.getInstance();
@@ -285,8 +292,8 @@ public class HandleConstructor {
assigns.add(assignment);
long fieldPos = (((long)field.sourceStart) << 32) | field.sourceEnd;
Argument parameter = new Argument(fieldName, fieldPos, copyType(field.type, source), Modifier.FINAL);
- Annotation[] nonNulls = findAnnotations(field, TransformationsUtil.NON_NULL_PATTERN);
- Annotation[] nullables = findAnnotations(field, TransformationsUtil.NULLABLE_PATTERN);
+ Annotation[] nonNulls = findAnnotations(field, NON_NULL_PATTERN);
+ Annotation[] nullables = findAnnotations(field, NULLABLE_PATTERN);
if (nonNulls.length != 0) {
Statement nullCheck = generateNullCheck(field, source);
if (nullCheck != null) nullChecks.add(nullCheck);
@@ -355,7 +362,7 @@ public class HandleConstructor {
Argument parameter = new Argument(field.name, fieldPos, copyType(field.type, source), Modifier.FINAL);
- Annotation[] copiedAnnotations = copyAnnotations(source, findAnnotations(field, TransformationsUtil.NON_NULL_PATTERN), findAnnotations(field, TransformationsUtil.NULLABLE_PATTERN));
+ Annotation[] copiedAnnotations = copyAnnotations(source, findAnnotations(field, NON_NULL_PATTERN), findAnnotations(field, NULLABLE_PATTERN));
if (copiedAnnotations.length != 0) parameter.annotations = copiedAnnotations;
params.add(parameter);
}
diff --git a/src/core/lombok/eclipse/handlers/HandleData.java b/src/core/lombok/eclipse/handlers/HandleData.java
index aa309489..a6a8842d 100644
--- a/src/core/lombok/eclipse/handlers/HandleData.java
+++ b/src/core/lombok/eclipse/handlers/HandleData.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009-2013 The Project Lombok Authors.
+ * Copyright (C) 2009-2014 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
@@ -21,9 +21,12 @@
*/
package lombok.eclipse.handlers;
+import static lombok.core.handlers.HandlerUtil.*;
+
import java.util.Collections;
import lombok.AccessLevel;
+import lombok.ConfigurationKeys;
import lombok.Data;
import lombok.core.AnnotationValues;
import lombok.eclipse.EclipseAnnotationHandler;
@@ -40,7 +43,9 @@ import org.mangosdk.spi.ProviderFor;
*/
@ProviderFor(EclipseAnnotationHandler.class)
public class HandleData extends EclipseAnnotationHandler<Data> {
- public void handle(AnnotationValues<Data> annotation, Annotation ast, EclipseNode annotationNode) {
+ @Override public void handle(AnnotationValues<Data> annotation, Annotation ast, EclipseNode annotationNode) {
+ handleFlagUsage(annotationNode, ConfigurationKeys.DATA_FLAG_USAGE, "@Data");
+
Data ann = annotation.getInstance();
EclipseNode typeNode = annotationNode.up();
diff --git a/src/core/lombok/eclipse/handlers/HandleEqualsAndHashCode.java b/src/core/lombok/eclipse/handlers/HandleEqualsAndHashCode.java
index 0cc0836e..2ae7aba4 100644
--- a/src/core/lombok/eclipse/handlers/HandleEqualsAndHashCode.java
+++ b/src/core/lombok/eclipse/handlers/HandleEqualsAndHashCode.java
@@ -21,6 +21,7 @@
*/
package lombok.eclipse.handlers;
+import static lombok.core.handlers.HandlerUtil.*;
import static lombok.eclipse.handlers.EclipseHandlerUtil.*;
import java.lang.reflect.Modifier;
@@ -33,6 +34,7 @@ import java.util.List;
import java.util.Set;
import lombok.AccessLevel;
+import lombok.ConfigurationKeys;
import lombok.EqualsAndHashCode;
import lombok.core.AST.Kind;
import lombok.core.handlers.HandlerUtil;
@@ -117,8 +119,9 @@ public class HandleEqualsAndHashCode extends EclipseAnnotationHandler<EqualsAndH
generateMethods(typeNode, errorNode, null, null, null, false, FieldAccess.GETTER);
}
- @Override public void handle(AnnotationValues<EqualsAndHashCode> annotation,
- Annotation ast, EclipseNode annotationNode) {
+ @Override public void handle(AnnotationValues<EqualsAndHashCode> annotation, Annotation ast, EclipseNode annotationNode) {
+ handleFlagUsage(annotationNode, ConfigurationKeys.EQUALS_AND_HASH_CODE_FLAG_USAGE, "@EqualsAndHashCode");
+
EqualsAndHashCode ann = annotation.getInstance();
List<String> excludes = Arrays.asList(ann.exclude());
List<String> includes = Arrays.asList(ann.of());
diff --git a/src/core/lombok/eclipse/handlers/HandleExtensionMethod.java b/src/core/lombok/eclipse/handlers/HandleExtensionMethod.java
index 3d30e8fe..8e53d873 100644
--- a/src/core/lombok/eclipse/handlers/HandleExtensionMethod.java
+++ b/src/core/lombok/eclipse/handlers/HandleExtensionMethod.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012 The Project Lombok Authors.
+ * Copyright (C) 2012-2014 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
@@ -21,6 +21,8 @@
*/
package lombok.eclipse.handlers;
+import static lombok.core.handlers.HandlerUtil.*;
+
import java.util.List;
import org.eclipse.jdt.internal.compiler.ast.Annotation;
@@ -28,6 +30,7 @@ import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
import org.mangosdk.spi.ProviderFor;
+import lombok.ConfigurationKeys;
import lombok.core.AnnotationValues;
import lombok.core.HandlerPriority;
import lombok.eclipse.EclipseAnnotationHandler;
@@ -39,6 +42,8 @@ import lombok.experimental.ExtensionMethod;
@HandlerPriority(66560) // 2^16 + 2^10; we must run AFTER HandleVal which is at 2^16
public class HandleExtensionMethod extends EclipseAnnotationHandler<ExtensionMethod> {
@Override public void handle(AnnotationValues<ExtensionMethod> annotation, Annotation ast, EclipseNode annotationNode) {
+ handleExperimentalFlagUsage(annotationNode, ConfigurationKeys.EXTENSION_METHOD_FLAG_USAGE, "@ExtensionMethod");
+
TypeDeclaration typeDecl = null;
EclipseNode owner = annotationNode.up();
if (owner.get() instanceof TypeDeclaration) typeDecl = (TypeDeclaration) owner.get();
diff --git a/src/core/lombok/eclipse/handlers/HandleFieldDefaults.java b/src/core/lombok/eclipse/handlers/HandleFieldDefaults.java
index d6d839cc..7d0702db 100644
--- a/src/core/lombok/eclipse/handlers/HandleFieldDefaults.java
+++ b/src/core/lombok/eclipse/handlers/HandleFieldDefaults.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012 The Project Lombok Authors.
+ * Copyright (C) 2012-2014 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
@@ -21,8 +21,10 @@
*/
package lombok.eclipse.handlers;
+import static lombok.core.handlers.HandlerUtil.*;
import static lombok.eclipse.handlers.EclipseHandlerUtil.*;
import lombok.AccessLevel;
+import lombok.ConfigurationKeys;
import lombok.core.AST.Kind;
import lombok.core.AnnotationValues;
import lombok.core.HandlerPriority;
@@ -102,6 +104,8 @@ public class HandleFieldDefaults extends EclipseAnnotationHandler<FieldDefaults>
}
public void handle(AnnotationValues<FieldDefaults> annotation, Annotation ast, EclipseNode annotationNode) {
+ handleExperimentalFlagUsage(annotationNode, ConfigurationKeys.FIELD_DEFAULTS_FLAG_USAGE, "@FieldDefaults");
+
EclipseNode node = annotationNode.up();
FieldDefaults instance = annotation.getInstance();
AccessLevel level = instance.level();
diff --git a/src/core/lombok/eclipse/handlers/HandleGetter.java b/src/core/lombok/eclipse/handlers/HandleGetter.java
index 188dfce2..8cffaa2c 100644
--- a/src/core/lombok/eclipse/handlers/HandleGetter.java
+++ b/src/core/lombok/eclipse/handlers/HandleGetter.java
@@ -21,6 +21,7 @@
*/
package lombok.eclipse.handlers;
+import static lombok.core.handlers.HandlerUtil.*;
import static lombok.eclipse.Eclipse.*;
import static lombok.eclipse.handlers.EclipseHandlerUtil.*;
@@ -32,11 +33,11 @@ import java.util.List;
import java.util.Map;
import lombok.AccessLevel;
+import lombok.ConfigurationKeys;
import lombok.Delegate;
import lombok.Getter;
import lombok.core.AST.Kind;
import lombok.core.AnnotationValues;
-import lombok.core.TransformationsUtil;
import lombok.eclipse.EclipseAnnotationHandler;
import lombok.eclipse.EclipseNode;
import lombok.eclipse.agent.PatchDelegate;
@@ -132,6 +133,8 @@ public class HandleGetter extends EclipseAnnotationHandler<Getter> {
}
public void handle(AnnotationValues<Getter> annotation, Annotation ast, EclipseNode annotationNode) {
+ handleFlagUsage(annotationNode, ConfigurationKeys.GETTER_FLAG_USAGE, "@Getter");
+
EclipseNode node = annotationNode.up();
Getter annotationInstance = annotation.getInstance();
AccessLevel level = annotationInstance.value();
@@ -269,8 +272,8 @@ public class HandleGetter extends EclipseAnnotationHandler<Getter> {
Annotation[] copiedAnnotations = copyAnnotations(source,
onMethod.toArray(new Annotation[0]),
- findAnnotations(field, TransformationsUtil.NON_NULL_PATTERN),
- findAnnotations(field, TransformationsUtil.NULLABLE_PATTERN),
+ findAnnotations(field, NON_NULL_PATTERN),
+ findAnnotations(field, NULLABLE_PATTERN),
findDelegatesAndMarkAsHandled(fieldNode),
deprecated);
diff --git a/src/core/lombok/eclipse/handlers/HandleLog.java b/src/core/lombok/eclipse/handlers/HandleLog.java
index cf1e8018..830190a2 100644
--- a/src/core/lombok/eclipse/handlers/HandleLog.java
+++ b/src/core/lombok/eclipse/handlers/HandleLog.java
@@ -21,15 +21,18 @@
*/
package lombok.eclipse.handlers;
-import static lombok.eclipse.Eclipse.*;
+import static lombok.core.handlers.HandlerUtil.*;
+import static lombok.eclipse.Eclipse.fromQualifiedName;
import static lombok.eclipse.handlers.EclipseHandlerUtil.*;
import java.lang.reflect.Modifier;
import java.util.Arrays;
+import lombok.ConfigurationKeys;
import lombok.core.AnnotationValues;
import lombok.eclipse.EclipseAnnotationHandler;
import lombok.eclipse.EclipseNode;
+import lombok.eclipse.handlers.EclipseHandlerUtil.MemberExistsResult;
import org.eclipse.jdt.internal.compiler.ast.Annotation;
import org.eclipse.jdt.internal.compiler.ast.ClassLiteralAccess;
@@ -49,10 +52,16 @@ public class HandleLog {
throw new UnsupportedOperationException();
}
- public static void processAnnotation(LoggingFramework framework, AnnotationValues<? extends java.lang.annotation.Annotation> annotation, Annotation source, EclipseNode annotationNode, String loggerCategory) {
+ public static void processAnnotation(LoggingFramework framework, AnnotationValues<? extends java.lang.annotation.Annotation> annotation, Annotation source, EclipseNode annotationNode, String loggerTopic) {
EclipseNode owner = annotationNode.up();
+
switch (owner.getKind()) {
case TYPE:
+ String 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));
+
TypeDeclaration typeDecl = null;
if (owner.get() instanceof TypeDeclaration) typeDecl = (TypeDeclaration) owner.get();
int modifiers = typeDecl == null ? 0 : typeDecl.modifiers;
@@ -65,14 +74,14 @@ public class HandleLog {
return;
}
- if (fieldExists("log", owner) != MemberExistsResult.NOT_EXISTS) {
- annotationNode.addWarning("Field 'log' already exists.");
+ if (fieldExists(logFieldName, owner) != MemberExistsResult.NOT_EXISTS) {
+ annotationNode.addWarning("Field '" + logFieldName + "' already exists.");
return;
}
ClassLiteralAccess loggingType = selfType(owner, source);
- FieldDeclaration fieldDeclaration = createField(framework, source, loggingType, loggerCategory);
+ FieldDeclaration fieldDeclaration = createField(framework, source, loggingType, logFieldName, 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);
@@ -98,16 +107,15 @@ public class HandleLog {
return result;
}
- public static FieldDeclaration createField(LoggingFramework framework, Annotation source, ClassLiteralAccess loggingType, String loggerCategory) {
+ private static FieldDeclaration createField(LoggingFramework framework, Annotation source, ClassLiteralAccess loggingType, String logFieldName, boolean useStatic, String loggerTopic) {
int pS = source.sourceStart, pE = source.sourceEnd;
long p = (long)pS << 32 | pE;
// private static final <loggerType> log = <factoryMethod>(<parameter>);
-
- FieldDeclaration fieldDecl = new FieldDeclaration("log".toCharArray(), 0, -1);
+ FieldDeclaration fieldDecl = new FieldDeclaration(logFieldName.toCharArray(), 0, -1);
setGeneratedBy(fieldDecl, source);
fieldDecl.declarationSourceEnd = -1;
- fieldDecl.modifiers = Modifier.PRIVATE | Modifier.STATIC | Modifier.FINAL;
+ fieldDecl.modifiers = Modifier.PRIVATE | (useStatic ? Modifier.STATIC : 0) | Modifier.FINAL;
fieldDecl.type = createTypeReference(framework.getLoggerTypeName(), source);
@@ -118,10 +126,10 @@ public class HandleLog {
factoryMethodCall.selector = framework.getLoggerFactoryMethodName().toCharArray();
Expression parameter;
- if (loggerCategory == null || loggerCategory.trim().length() == 0) {
+ if (loggerTopic == null || loggerTopic.trim().length() == 0) {
parameter = framework.createFactoryParameter(loggingType, source);
} else {
- parameter = new StringLiteral(loggerCategory.toCharArray(), pS, pE, 0);
+ parameter = new StringLiteral(loggerTopic.toCharArray(), pS, pE, 0);
}
factoryMethodCall.arguments = new Expression[] { parameter };
@@ -161,6 +169,7 @@ public class HandleLog {
@ProviderFor(EclipseAnnotationHandler.class)
public static class HandleCommonsLog extends EclipseAnnotationHandler<lombok.extern.apachecommons.CommonsLog> {
@Override public void handle(AnnotationValues<lombok.extern.apachecommons.CommonsLog> annotation, Annotation source, EclipseNode annotationNode) {
+ handleFlagUsage(annotationNode, ConfigurationKeys.LOG_COMMONS_FLAG_USAGE, "@apachecommons.CommonsLog", ConfigurationKeys.LOG_ANY_FLAG_USAGE, "any @Log");
processAnnotation(LoggingFramework.COMMONS, annotation, source, annotationNode, annotation.getInstance().topic());
}
}
@@ -171,6 +180,7 @@ public class HandleLog {
@ProviderFor(EclipseAnnotationHandler.class)
public static class HandleJulLog extends EclipseAnnotationHandler<lombok.extern.java.Log> {
@Override public void handle(AnnotationValues<lombok.extern.java.Log> annotation, Annotation source, EclipseNode annotationNode) {
+ handleFlagUsage(annotationNode, ConfigurationKeys.LOG_JUL_FLAG_USAGE, "@java.Log", ConfigurationKeys.LOG_ANY_FLAG_USAGE, "any @Log");
processAnnotation(LoggingFramework.JUL, annotation, source, annotationNode, annotation.getInstance().topic());
}
}
@@ -181,6 +191,7 @@ public class HandleLog {
@ProviderFor(EclipseAnnotationHandler.class)
public static class HandleLog4jLog extends EclipseAnnotationHandler<lombok.extern.log4j.Log4j> {
@Override public void handle(AnnotationValues<lombok.extern.log4j.Log4j> annotation, Annotation source, EclipseNode annotationNode) {
+ handleFlagUsage(annotationNode, ConfigurationKeys.LOG_LOG4J_FLAG_USAGE, "@Log4j", ConfigurationKeys.LOG_ANY_FLAG_USAGE, "any @Log");
processAnnotation(LoggingFramework.LOG4J, annotation, source, annotationNode, annotation.getInstance().topic());
}
}
@@ -191,6 +202,7 @@ public class HandleLog {
@ProviderFor(EclipseAnnotationHandler.class)
public static class HandleLog4j2Log extends EclipseAnnotationHandler<lombok.extern.log4j.Log4j2> {
@Override public void handle(AnnotationValues<lombok.extern.log4j.Log4j2> annotation, Annotation source, EclipseNode annotationNode) {
+ handleFlagUsage(annotationNode, ConfigurationKeys.LOG_LOG4J2_FLAG_USAGE, "@Log4j2", ConfigurationKeys.LOG_ANY_FLAG_USAGE, "any @Log");
processAnnotation(LoggingFramework.LOG4J2, annotation, source, annotationNode, annotation.getInstance().topic());
}
}
@@ -201,6 +213,7 @@ public class HandleLog {
@ProviderFor(EclipseAnnotationHandler.class)
public static class HandleSlf4jLog extends EclipseAnnotationHandler<lombok.extern.slf4j.Slf4j> {
@Override public void handle(AnnotationValues<lombok.extern.slf4j.Slf4j> annotation, Annotation source, EclipseNode annotationNode) {
+ handleFlagUsage(annotationNode, ConfigurationKeys.LOG_SLF4J_FLAG_USAGE, "@Slf4j", ConfigurationKeys.LOG_ANY_FLAG_USAGE, "any @Log");
processAnnotation(LoggingFramework.SLF4J, annotation, source, annotationNode, annotation.getInstance().topic());
}
}
@@ -211,6 +224,7 @@ public class HandleLog {
@ProviderFor(EclipseAnnotationHandler.class)
public static class HandleXSlf4jLog extends EclipseAnnotationHandler<lombok.extern.slf4j.XSlf4j> {
@Override public void handle(AnnotationValues<lombok.extern.slf4j.XSlf4j> annotation, Annotation source, EclipseNode annotationNode) {
+ handleFlagUsage(annotationNode, ConfigurationKeys.LOG_XSLF4J_FLAG_USAGE, "@XSlf4j", ConfigurationKeys.LOG_ANY_FLAG_USAGE, "any @Log");
processAnnotation(LoggingFramework.XSLF4J, annotation, source, annotationNode, annotation.getInstance().topic());
}
}
diff --git a/src/core/lombok/eclipse/handlers/HandleNonNull.java b/src/core/lombok/eclipse/handlers/HandleNonNull.java
index 7fd12ca3..79bb7a08 100644
--- a/src/core/lombok/eclipse/handlers/HandleNonNull.java
+++ b/src/core/lombok/eclipse/handlers/HandleNonNull.java
@@ -21,11 +21,13 @@
*/
package lombok.eclipse.handlers;
+import static lombok.core.handlers.HandlerUtil.*;
import static lombok.eclipse.Eclipse.isPrimitive;
import static lombok.eclipse.handlers.EclipseHandlerUtil.*;
import java.util.Arrays;
+import lombok.ConfigurationKeys;
import lombok.NonNull;
import lombok.core.AST.Kind;
import lombok.core.AnnotationValues;
@@ -57,6 +59,8 @@ import org.mangosdk.spi.ProviderFor;
@HandlerPriority(value = 512) // 2^9; onParameter=@__(@NonNull) has to run first.
public class HandleNonNull extends EclipseAnnotationHandler<NonNull> {
@Override public void handle(AnnotationValues<NonNull> annotation, Annotation ast, EclipseNode annotationNode) {
+ handleFlagUsage(annotationNode, ConfigurationKeys.NON_NULL_FLAG_USAGE, "@NonNull");
+
if (annotationNode.up().getKind() == Kind.FIELD) {
// This is meaningless unless the field is used to generate a method (@Setter, @RequiredArgsConstructor, etc),
// but in that case those handlers will take care of it. However, we DO check if the annotation is applied to
diff --git a/src/core/lombok/eclipse/handlers/HandlePrintAST.java b/src/core/lombok/eclipse/handlers/HandlePrintAST.java
index da6fa2a2..65cda98a 100644
--- a/src/core/lombok/eclipse/handlers/HandlePrintAST.java
+++ b/src/core/lombok/eclipse/handlers/HandlePrintAST.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009-2012 The Project Lombok Authors.
+ * Copyright (C) 2009-2014 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
@@ -52,7 +52,16 @@ public class HandlePrintAST extends EclipseAnnotationHandler<PrintAST> {
} catch (FileNotFoundException e) {
Lombok.sneakyThrow(e);
}
-
- annotationNode.up().traverse(new EclipseASTVisitor.Printer(annotation.getInstance().printContent(), stream, annotation.getInstance().printPositions()));
+ try {
+ annotationNode.up().traverse(new EclipseASTVisitor.Printer(annotation.getInstance().printContent(), stream, annotation.getInstance().printPositions()));
+ } finally {
+ if (stream != System.out) {
+ try {
+ stream.close();
+ } catch (Exception e) {
+ Lombok.sneakyThrow(e);
+ }
+ }
+ }
}
-}
+} \ No newline at end of file
diff --git a/src/core/lombok/eclipse/handlers/HandleSetter.java b/src/core/lombok/eclipse/handlers/HandleSetter.java
index caa5329a..74ef07b5 100644
--- a/src/core/lombok/eclipse/handlers/HandleSetter.java
+++ b/src/core/lombok/eclipse/handlers/HandleSetter.java
@@ -21,6 +21,7 @@
*/
package lombok.eclipse.handlers;
+import static lombok.core.handlers.HandlerUtil.*;
import static lombok.eclipse.Eclipse.*;
import static lombok.eclipse.handlers.EclipseHandlerUtil.*;
@@ -31,10 +32,10 @@ import java.util.Collections;
import java.util.List;
import lombok.AccessLevel;
+import lombok.ConfigurationKeys;
import lombok.Setter;
import lombok.core.AST.Kind;
import lombok.core.AnnotationValues;
-import lombok.core.TransformationsUtil;
import lombok.eclipse.EclipseAnnotationHandler;
import lombok.eclipse.EclipseNode;
import lombok.eclipse.handlers.EclipseHandlerUtil.FieldAccess;
@@ -118,6 +119,8 @@ public class HandleSetter extends EclipseAnnotationHandler<Setter> {
}
public void handle(AnnotationValues<Setter> annotation, Annotation ast, EclipseNode annotationNode) {
+ handleFlagUsage(annotationNode, ConfigurationKeys.SETTER_FLAG_USAGE, "@Setter");
+
EclipseNode node = annotationNode.up();
AccessLevel level = annotation.getInstance().value();
if (level == AccessLevel.NONE || node == null) return;
@@ -230,8 +233,8 @@ public class HandleSetter extends EclipseAnnotationHandler<Setter> {
method.bodyStart = method.declarationSourceStart = method.sourceStart = source.sourceStart;
method.bodyEnd = method.declarationSourceEnd = method.sourceEnd = source.sourceEnd;
- Annotation[] nonNulls = findAnnotations(field, TransformationsUtil.NON_NULL_PATTERN);
- Annotation[] nullables = findAnnotations(field, TransformationsUtil.NULLABLE_PATTERN);
+ Annotation[] nonNulls = findAnnotations(field, NON_NULL_PATTERN);
+ Annotation[] nullables = findAnnotations(field, NULLABLE_PATTERN);
List<Statement> statements = new ArrayList<Statement>(5);
if (nonNulls.length == 0) {
statements.add(assignment);
diff --git a/src/core/lombok/eclipse/handlers/HandleSneakyThrows.java b/src/core/lombok/eclipse/handlers/HandleSneakyThrows.java
index d8261326..481dbcde 100644
--- a/src/core/lombok/eclipse/handlers/HandleSneakyThrows.java
+++ b/src/core/lombok/eclipse/handlers/HandleSneakyThrows.java
@@ -21,6 +21,7 @@
*/
package lombok.eclipse.handlers;
+import static lombok.core.handlers.HandlerUtil.*;
import static lombok.eclipse.handlers.EclipseHandlerUtil.*;
import java.lang.reflect.Modifier;
@@ -28,6 +29,7 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
+import lombok.ConfigurationKeys;
import lombok.SneakyThrows;
import lombok.core.AnnotationValues;
import lombok.core.HandlerPriority;
@@ -75,6 +77,8 @@ public class HandleSneakyThrows extends EclipseAnnotationHandler<SneakyThrows> {
}
@Override public void handle(AnnotationValues<SneakyThrows> annotation, Annotation source, EclipseNode annotationNode) {
+ handleFlagUsage(annotationNode, ConfigurationKeys.SNEAKY_THROWS_FLAG_USAGE, "@SneakyThrows");
+
List<String> exceptionNames = annotation.getRawExpressions("value");
List<DeclaredException> exceptions = new ArrayList<DeclaredException>();
diff --git a/src/core/lombok/eclipse/handlers/HandleSynchronized.java b/src/core/lombok/eclipse/handlers/HandleSynchronized.java
index b3e51da0..a45a499c 100644
--- a/src/core/lombok/eclipse/handlers/HandleSynchronized.java
+++ b/src/core/lombok/eclipse/handlers/HandleSynchronized.java
@@ -21,10 +21,12 @@
*/
package lombok.eclipse.handlers;
+import static lombok.core.handlers.HandlerUtil.*;
import static lombok.eclipse.handlers.EclipseHandlerUtil.*;
import java.lang.reflect.Modifier;
+import lombok.ConfigurationKeys;
import lombok.Synchronized;
import lombok.core.AnnotationValues;
import lombok.core.HandlerPriority;
@@ -105,6 +107,8 @@ public class HandleSynchronized extends EclipseAnnotationHandler<Synchronized> {
}
@Override public void handle(AnnotationValues<Synchronized> annotation, Annotation source, EclipseNode annotationNode) {
+ handleFlagUsage(annotationNode, ConfigurationKeys.SYNCHRONIZED_FLAG_USAGE, "@Synchronized");
+
int p1 = source.sourceStart -1;
int p2 = source.sourceStart -2;
long pos = (((long)p1) << 32) | p2;
diff --git a/src/core/lombok/eclipse/handlers/HandleToString.java b/src/core/lombok/eclipse/handlers/HandleToString.java
index 31ff3021..a4ed254a 100644
--- a/src/core/lombok/eclipse/handlers/HandleToString.java
+++ b/src/core/lombok/eclipse/handlers/HandleToString.java
@@ -21,6 +21,7 @@
*/
package lombok.eclipse.handlers;
+import static lombok.core.handlers.HandlerUtil.*;
import static lombok.eclipse.handlers.EclipseHandlerUtil.*;
import java.util.ArrayList;
@@ -32,12 +33,14 @@ import java.util.List;
import java.util.Set;
import lombok.AccessLevel;
+import lombok.ConfigurationKeys;
import lombok.ToString;
-import lombok.core.AnnotationValues;
import lombok.core.AST.Kind;
+import lombok.core.AnnotationValues;
import lombok.eclipse.Eclipse;
import lombok.eclipse.EclipseAnnotationHandler;
import lombok.eclipse.EclipseNode;
+import lombok.eclipse.handlers.EclipseHandlerUtil.FieldAccess;
import org.eclipse.jdt.internal.compiler.ast.ASTNode;
import org.eclipse.jdt.internal.compiler.ast.Annotation;
@@ -88,12 +91,15 @@ public class HandleToString extends EclipseAnnotationHandler<ToString> {
boolean includeFieldNames = true;
try {
- includeFieldNames = ((Boolean)ToString.class.getMethod("includeFieldNames").getDefaultValue()).booleanValue();
+ Boolean configuration = typeNode.getAst().readConfiguration(ConfigurationKeys.TO_STRING_INCLUDE_FIELD_NAMES);
+ includeFieldNames = configuration != null ? configuration : ((Boolean)ToString.class.getMethod("includeFieldNames").getDefaultValue()).booleanValue();
} catch (Exception ignore) {}
generateToString(typeNode, errorNode, null, null, includeFieldNames, null, false, FieldAccess.GETTER);
}
public void handle(AnnotationValues<ToString> annotation, Annotation ast, EclipseNode annotationNode) {
+ handleFlagUsage(annotationNode, ConfigurationKeys.TO_STRING_FLAG_USAGE, "@ToString");
+
ToString ann = annotation.getInstance();
List<String> excludes = Arrays.asList(ann.exclude());
List<String> includes = Arrays.asList(ann.of());
@@ -111,9 +117,14 @@ public class HandleToString extends EclipseAnnotationHandler<ToString> {
checkForBogusFieldNames(typeNode, annotation);
- FieldAccess fieldAccess = ann.doNotUseGetters() ? FieldAccess.PREFER_FIELD : FieldAccess.GETTER;
+ Boolean doNotUseGettersConfiguration = annotationNode.getAst().readConfiguration(ConfigurationKeys.TO_STRING_DO_NOT_USE_GETTERS);
+ boolean doNotUseGetters = annotation.isExplicit("doNotUseGetters") || doNotUseGettersConfiguration == null ? ann.doNotUseGetters() : doNotUseGettersConfiguration;
+ FieldAccess fieldAccess = doNotUseGetters ? FieldAccess.PREFER_FIELD : FieldAccess.GETTER;
- generateToString(typeNode, annotationNode, excludes, includes, ann.includeFieldNames(), callSuper, true, fieldAccess);
+ Boolean fieldNamesConfiguration = annotationNode.getAst().readConfiguration(ConfigurationKeys.TO_STRING_INCLUDE_FIELD_NAMES);
+ boolean includeFieldNames = annotation.isExplicit("includeFieldNames") || fieldNamesConfiguration == null ? ann.includeFieldNames() : fieldNamesConfiguration;
+
+ generateToString(typeNode, annotationNode, excludes, includes, includeFieldNames, callSuper, true, fieldAccess);
}
public void generateToString(EclipseNode typeNode, EclipseNode errorNode, List<String> excludes, List<String> includes,
diff --git a/src/core/lombok/eclipse/handlers/HandleVal.java b/src/core/lombok/eclipse/handlers/HandleVal.java
index c8339f35..d4ae417c 100644
--- a/src/core/lombok/eclipse/handlers/HandleVal.java
+++ b/src/core/lombok/eclipse/handlers/HandleVal.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010-2012 The Project Lombok Authors.
+ * Copyright (C) 2010-2014 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
@@ -21,6 +21,8 @@
*/
package lombok.eclipse.handlers;
+import static lombok.core.handlers.HandlerUtil.*;
+import lombok.ConfigurationKeys;
import lombok.val;
import lombok.core.HandlerPriority;
import lombok.eclipse.DeferUntilPostDiet;
@@ -43,6 +45,8 @@ import org.mangosdk.spi.ProviderFor;
public class HandleVal extends EclipseASTAdapter {
@Override public void visitLocal(EclipseNode localNode, LocalDeclaration local) {
if (!EclipseHandlerUtil.typeMatches(val.class, localNode, local.type)) return;
+ handleFlagUsage(localNode, ConfigurationKeys.VAL_FLAG_USAGE, "val");
+
boolean variableOfForEach = false;
if (localNode.directUp().get() instanceof ForeachStatement) {
diff --git a/src/core/lombok/eclipse/handlers/HandleValue.java b/src/core/lombok/eclipse/handlers/HandleValue.java
index 0607137b..211b337a 100644
--- a/src/core/lombok/eclipse/handlers/HandleValue.java
+++ b/src/core/lombok/eclipse/handlers/HandleValue.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012-2013 The Project Lombok Authors.
+ * Copyright (C) 2012-2014 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
@@ -21,11 +21,13 @@
*/
package lombok.eclipse.handlers;
+import static lombok.core.handlers.HandlerUtil.*;
import static lombok.eclipse.handlers.EclipseHandlerUtil.*;
import java.util.Collections;
import lombok.AccessLevel;
+import lombok.ConfigurationKeys;
import lombok.core.AnnotationValues;
import lombok.core.HandlerPriority;
import lombok.eclipse.EclipseAnnotationHandler;
@@ -46,6 +48,8 @@ import org.mangosdk.spi.ProviderFor;
@HandlerPriority(-512) //-2^9; to ensure @EqualsAndHashCode and such pick up on this handler making the class final and messing with the fields' access levels, run earlier.
public class HandleValue extends EclipseAnnotationHandler<Value> {
public void handle(AnnotationValues<Value> annotation, Annotation ast, EclipseNode annotationNode) {
+ handleFlagUsage(annotationNode, ConfigurationKeys.VALUE_FLAG_USAGE, "@Value");
+
Value ann = annotation.getInstance();
EclipseNode typeNode = annotationNode.up();
diff --git a/src/core/lombok/eclipse/handlers/HandleWither.java b/src/core/lombok/eclipse/handlers/HandleWither.java
index 305e0a16..30306b72 100644
--- a/src/core/lombok/eclipse/handlers/HandleWither.java
+++ b/src/core/lombok/eclipse/handlers/HandleWither.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012-2013 The Project Lombok Authors.
+ * Copyright (C) 2012-2014 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
@@ -21,6 +21,7 @@
*/
package lombok.eclipse.handlers;
+import static lombok.core.handlers.HandlerUtil.*;
import static lombok.eclipse.Eclipse.*;
import static lombok.eclipse.handlers.EclipseHandlerUtil.*;
@@ -31,9 +32,9 @@ import java.util.Collections;
import java.util.List;
import lombok.AccessLevel;
+import lombok.ConfigurationKeys;
import lombok.core.AST.Kind;
import lombok.core.AnnotationValues;
-import lombok.core.TransformationsUtil;
import lombok.eclipse.EclipseAnnotationHandler;
import lombok.eclipse.EclipseNode;
import lombok.eclipse.handlers.EclipseHandlerUtil.FieldAccess;
@@ -120,6 +121,8 @@ public class HandleWither extends EclipseAnnotationHandler<Wither> {
}
@Override public void handle(AnnotationValues<Wither> annotation, Annotation ast, EclipseNode annotationNode) {
+ handleExperimentalFlagUsage(annotationNode, ConfigurationKeys.WITHER_FLAG_USAGE, "@Wither");
+
EclipseNode node = annotationNode.up();
AccessLevel level = annotation.getInstance().value();
if (level == AccessLevel.NONE || node == null) return;
@@ -266,8 +269,8 @@ public class HandleWither extends EclipseAnnotationHandler<Wither> {
method.bodyStart = method.declarationSourceStart = method.sourceStart = source.sourceStart;
method.bodyEnd = method.declarationSourceEnd = method.sourceEnd = source.sourceEnd;
- Annotation[] nonNulls = findAnnotations(field, TransformationsUtil.NON_NULL_PATTERN);
- Annotation[] nullables = findAnnotations(field, TransformationsUtil.NULLABLE_PATTERN);
+ Annotation[] nonNulls = findAnnotations(field, NON_NULL_PATTERN);
+ Annotation[] nullables = findAnnotations(field, NULLABLE_PATTERN);
List<Statement> statements = new ArrayList<Statement>(5);
if (nonNulls.length > 0) {
Statement nullCheck = generateNullCheck(field, source);
diff --git a/src/core/lombok/experimental/Accessors.java b/src/core/lombok/experimental/Accessors.java
index 2748bfa9..c2a0ca16 100644
--- a/src/core/lombok/experimental/Accessors.java
+++ b/src/core/lombok/experimental/Accessors.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012 The Project Lombok Authors.
+ * Copyright (C) 2012-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
diff --git a/src/core/lombok/experimental/ExtensionMethod.java b/src/core/lombok/experimental/ExtensionMethod.java
index 44f28d04..7de8a136 100644
--- a/src/core/lombok/experimental/ExtensionMethod.java
+++ b/src/core/lombok/experimental/ExtensionMethod.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012 The Project Lombok Authors.
+ * Copyright (C) 2012-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
diff --git a/src/core/lombok/experimental/FieldDefaults.java b/src/core/lombok/experimental/FieldDefaults.java
index 8a3fb534..1c621f3c 100644
--- a/src/core/lombok/experimental/FieldDefaults.java
+++ b/src/core/lombok/experimental/FieldDefaults.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012 The Project Lombok Authors.
+ * Copyright (C) 2012-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
diff --git a/src/core/lombok/extern/apachecommons/CommonsLog.java b/src/core/lombok/extern/apachecommons/CommonsLog.java
index 2e31edf7..45345098 100644
--- a/src/core/lombok/extern/apachecommons/CommonsLog.java
+++ b/src/core/lombok/extern/apachecommons/CommonsLog.java
@@ -63,4 +63,4 @@ public @interface CommonsLog {
* Sets the category of the constructed Logger. By default, it will use the type where the annotation is placed.
*/
String topic() default "";
-} \ No newline at end of file
+}
diff --git a/src/core/lombok/extern/java/Log.java b/src/core/lombok/extern/java/Log.java
index f8cbf03f..bac2742e 100644
--- a/src/core/lombok/extern/java/Log.java
+++ b/src/core/lombok/extern/java/Log.java
@@ -62,4 +62,4 @@ public @interface Log {
* Sets the category of the constructed Logger. By default, it will use the type where the annotation is placed.
*/
String topic() default "";
-} \ No newline at end of file
+}
diff --git a/src/core/lombok/extern/log4j/Log4j.java b/src/core/lombok/extern/log4j/Log4j.java
index d3164047..9490acb8 100644
--- a/src/core/lombok/extern/log4j/Log4j.java
+++ b/src/core/lombok/extern/log4j/Log4j.java
@@ -63,4 +63,4 @@ public @interface Log4j {
* Sets the category of the constructed Logger. By default, it will use the type where the annotation is placed.
*/
String topic() default "";
-} \ No newline at end of file
+}
diff --git a/src/core/lombok/extern/log4j/Log4j2.java b/src/core/lombok/extern/log4j/Log4j2.java
index 0267d98c..43125e6b 100644
--- a/src/core/lombok/extern/log4j/Log4j2.java
+++ b/src/core/lombok/extern/log4j/Log4j2.java
@@ -63,4 +63,4 @@ public @interface Log4j2 {
* Sets the category of the constructed Logger. By default, it will use the type where the annotation is placed.
*/
String topic() default "";
-} \ No newline at end of file
+}
diff --git a/src/core/lombok/extern/slf4j/Slf4j.java b/src/core/lombok/extern/slf4j/Slf4j.java
index 5d6e7d8c..04df6498 100644
--- a/src/core/lombok/extern/slf4j/Slf4j.java
+++ b/src/core/lombok/extern/slf4j/Slf4j.java
@@ -25,6 +25,7 @@ import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
+
/**
* Causes lombok to generate a logger field.
* <p>
@@ -62,3 +63,4 @@ public @interface Slf4j {
*/
String topic() default "";
}
+
diff --git a/src/core/lombok/extern/slf4j/XSlf4j.java b/src/core/lombok/extern/slf4j/XSlf4j.java
index 0f2efe26..8a311c79 100644
--- a/src/core/lombok/extern/slf4j/XSlf4j.java
+++ b/src/core/lombok/extern/slf4j/XSlf4j.java
@@ -25,6 +25,7 @@ import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
+
/**
* Causes lombok to generate a logger field.
* <p>
diff --git a/src/core/lombok/javac/HandlerLibrary.java b/src/core/lombok/javac/HandlerLibrary.java
index 4306b5f2..0905170b 100644
--- a/src/core/lombok/javac/HandlerLibrary.java
+++ b/src/core/lombok/javac/HandlerLibrary.java
@@ -40,6 +40,7 @@ import lombok.core.SpiLoadUtil;
import lombok.core.TypeLibrary;
import lombok.core.TypeResolver;
import lombok.core.AnnotationValues.AnnotationValueDecodeFail;
+import lombok.core.configuration.ConfigurationKeysLoader;
import lombok.javac.handlers.JavacHandlerUtil;
import com.sun.tools.javac.tree.JCTree;
@@ -63,6 +64,7 @@ public class HandlerLibrary {
* You probably want to use {@link #load(Messager)} instead.
*/
public HandlerLibrary(Messager messager) {
+ ConfigurationKeysLoader.LoaderLoader.loadAllConfigurationKeys();
this.messager = messager;
}
diff --git a/src/core/lombok/javac/JavacAST.java b/src/core/lombok/javac/JavacAST.java
index 31bdc3a6..4e553063 100644
--- a/src/core/lombok/javac/JavacAST.java
+++ b/src/core/lombok/javac/JavacAST.java
@@ -22,6 +22,7 @@
package lombok.javac;
import java.lang.reflect.Field;
+import java.net.URI;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
@@ -88,7 +89,16 @@ public class JavacAST extends AST<JavacAST, JavacNode, JCTree> {
this.javacTypes = JavacTypes.instance(context);
clearChanged();
}
-
+
+ @Override public URI getAbsoluteFileLocation() {
+ try {
+ JCCompilationUnit cu = (JCCompilationUnit) top().get();
+ return cu.sourcefile.toUri();
+ } catch (Exception e) {
+ return null;
+ }
+ }
+
private static String sourceName(JCCompilationUnit cu) {
return cu.sourcefile == null ? null : cu.sourcefile.toString();
}
@@ -385,7 +395,7 @@ public class JavacAST extends AST<JavacAST, JavacNode, JCTree> {
}
}
- private void removeFromDeferredDiagnostics(int startPos, int endPos) {
+ public void removeFromDeferredDiagnostics(int startPos, int endPos) {
JCCompilationUnit self = (JCCompilationUnit) top().get();
new CompilerMessageSuppressor(getContext()).removeAllBetween(self.sourcefile, startPos, endPos);
}
diff --git a/src/core/lombok/javac/handlers/HandleAccessors.java b/src/core/lombok/javac/handlers/HandleAccessors.java
index e2489bda..46fe1cd2 100644
--- a/src/core/lombok/javac/handlers/HandleAccessors.java
+++ b/src/core/lombok/javac/handlers/HandleAccessors.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012 The Project Lombok Authors.
+ * Copyright (C) 2012-2014 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
@@ -21,12 +21,14 @@
*/
package lombok.javac.handlers;
+import static lombok.core.handlers.HandlerUtil.*;
import static lombok.javac.handlers.JavacHandlerUtil.*;
import org.mangosdk.spi.ProviderFor;
import com.sun.tools.javac.tree.JCTree.JCAnnotation;
+import lombok.ConfigurationKeys;
import lombok.core.AnnotationValues;
import lombok.core.HandlerPriority;
import lombok.experimental.Accessors;
@@ -39,6 +41,9 @@ public class HandleAccessors extends JavacAnnotationHandler<Accessors> {
@Override public void handle(AnnotationValues<Accessors> annotation, JCAnnotation ast, JavacNode annotationNode) {
// Accessors itself is handled by HandleGetter/Setter; this is just to ensure that the annotation is removed
// from the AST when delomboking.
+
+ handleExperimentalFlagUsage(annotationNode, ConfigurationKeys.ACCESSORS_FLAG_USAGE, "@Accessors");
+
deleteAnnotationIfNeccessary(annotationNode, Accessors.class);
}
}
diff --git a/src/core/lombok/javac/handlers/HandleBuilder.java b/src/core/lombok/javac/handlers/HandleBuilder.java
index 1fc2941e..b382395e 100644
--- a/src/core/lombok/javac/handlers/HandleBuilder.java
+++ b/src/core/lombok/javac/handlers/HandleBuilder.java
@@ -46,10 +46,10 @@ import com.sun.tools.javac.util.ListBuffer;
import com.sun.tools.javac.util.Name;
import lombok.AccessLevel;
+import lombok.ConfigurationKeys;
import lombok.core.AST.Kind;
import lombok.core.AnnotationValues;
import lombok.core.HandlerPriority;
-import lombok.core.TransformationsUtil;
import lombok.experimental.Builder;
import lombok.experimental.NonFinal;
import lombok.javac.JavacAnnotationHandler;
@@ -65,6 +65,8 @@ import static lombok.javac.JavacTreeMaker.TypeTag.*;
@HandlerPriority(-1024) //-2^10; to ensure we've picked up @FieldDefault's changes (-2048) but @Value hasn't removed itself yet (-512), so that we can error on presence of it on the builder classes.
public class HandleBuilder extends JavacAnnotationHandler<Builder> {
@Override public void handle(AnnotationValues<Builder> annotation, JCAnnotation ast, JavacNode annotationNode) {
+ handleExperimentalFlagUsage(annotationNode, ConfigurationKeys.BUILDER_FLAG_USAGE, "@Builder");
+
Builder builderInstance = annotation.getInstance();
String builderMethodName = builderInstance.builderMethodName();
String buildMethodName = builderInstance.buildMethodName();
@@ -307,7 +309,7 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> {
}
boolean isBoolean = isBoolean(fieldNode);
- String setterName = fluent ? fieldNode.getName() : TransformationsUtil.toSetterName(null, fieldNode.getName(), isBoolean);
+ String setterName = fluent ? fieldNode.getName() : toSetterName(builderType.getAst(), null, fieldNode.getName(), isBoolean);
JavacTreeMaker maker = builderType.getTreeMaker();
return HandleSetter.createSetter(Flags.PUBLIC, fieldNode, maker, setterName, chain, source, List.<JCAnnotation>nil(), List.<JCAnnotation>nil());
diff --git a/src/core/lombok/javac/handlers/HandleCleanup.java b/src/core/lombok/javac/handlers/HandleCleanup.java
index 12e7227d..4aa61764 100644
--- a/src/core/lombok/javac/handlers/HandleCleanup.java
+++ b/src/core/lombok/javac/handlers/HandleCleanup.java
@@ -21,9 +21,11 @@
*/
package lombok.javac.handlers;
+import static lombok.core.handlers.HandlerUtil.*;
import static lombok.javac.handlers.JavacHandlerUtil.*;
import static lombok.javac.Javac.*;
import lombok.Cleanup;
+import lombok.ConfigurationKeys;
import lombok.core.AST.Kind;
import lombok.core.AnnotationValues;
import lombok.delombok.LombokOptionsFactory;
@@ -61,6 +63,8 @@ import com.sun.tools.javac.util.Name;
@ProviderFor(JavacAnnotationHandler.class)
public class HandleCleanup extends JavacAnnotationHandler<Cleanup> {
@Override public void handle(AnnotationValues<Cleanup> annotation, JCAnnotation ast, JavacNode annotationNode) {
+ handleFlagUsage(annotationNode, ConfigurationKeys.CLEANUP_FLAG_USAGE, "@Cleanup");
+
if (inNetbeansEditor(annotationNode)) return;
deleteAnnotationIfNeccessary(annotationNode, Cleanup.class);
diff --git a/src/core/lombok/javac/handlers/HandleConstructor.java b/src/core/lombok/javac/handlers/HandleConstructor.java
index b8762ed8..adfa253f 100644
--- a/src/core/lombok/javac/handlers/HandleConstructor.java
+++ b/src/core/lombok/javac/handlers/HandleConstructor.java
@@ -21,13 +21,14 @@
*/
package lombok.javac.handlers;
+import static lombok.core.handlers.HandlerUtil.*;
import static lombok.javac.handlers.JavacHandlerUtil.*;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
+import lombok.ConfigurationKeys;
import lombok.NoArgsConstructor;
import lombok.RequiredArgsConstructor;
import lombok.core.AnnotationValues;
-import lombok.core.TransformationsUtil;
import lombok.core.AST.Kind;
import lombok.delombok.LombokOptionsFactory;
import lombok.experimental.Builder;
@@ -59,6 +60,8 @@ public class HandleConstructor {
@ProviderFor(JavacAnnotationHandler.class)
public static class HandleNoArgsConstructor extends JavacAnnotationHandler<NoArgsConstructor> {
@Override public void handle(AnnotationValues<NoArgsConstructor> annotation, JCAnnotation ast, JavacNode annotationNode) {
+ handleFlagUsage(annotationNode, ConfigurationKeys.NO_ARGS_CONSTRUCTOR_FLAG_USAGE, "@NoArgsConstructor", ConfigurationKeys.ANY_CONSTRUCTOR_FLAG_USAGE, "any @xArgsConstructor");
+
deleteAnnotationIfNeccessary(annotationNode, NoArgsConstructor.class);
deleteImportFromCompilationUnit(annotationNode, "lombok.AccessLevel");
JavacNode typeNode = annotationNode.up();
@@ -76,6 +79,8 @@ public class HandleConstructor {
@ProviderFor(JavacAnnotationHandler.class)
public static class HandleRequiredArgsConstructor extends JavacAnnotationHandler<RequiredArgsConstructor> {
@Override public void handle(AnnotationValues<RequiredArgsConstructor> annotation, JCAnnotation ast, JavacNode annotationNode) {
+ handleFlagUsage(annotationNode, ConfigurationKeys.REQUIRED_ARGS_CONSTRUCTOR_FLAG_USAGE, "@RequiredArgsConstructor", ConfigurationKeys.ANY_CONSTRUCTOR_FLAG_USAGE, "any @xArgsConstructor");
+
deleteAnnotationIfNeccessary(annotationNode, RequiredArgsConstructor.class);
deleteImportFromCompilationUnit(annotationNode, "lombok.AccessLevel");
JavacNode typeNode = annotationNode.up();
@@ -102,7 +107,7 @@ public class HandleConstructor {
//Skip static fields.
if ((fieldFlags & Flags.STATIC) != 0) continue;
boolean isFinal = (fieldFlags & Flags.FINAL) != 0;
- boolean isNonNull = !findAnnotations(child, TransformationsUtil.NON_NULL_PATTERN).isEmpty();
+ boolean isNonNull = !findAnnotations(child, NON_NULL_PATTERN).isEmpty();
if ((isFinal || isNonNull) && fieldDecl.init == null) fields.append(child);
}
return fields.toList();
@@ -111,6 +116,8 @@ public class HandleConstructor {
@ProviderFor(JavacAnnotationHandler.class)
public static class HandleAllArgsConstructor extends JavacAnnotationHandler<AllArgsConstructor> {
@Override public void handle(AnnotationValues<AllArgsConstructor> annotation, JCAnnotation ast, JavacNode annotationNode) {
+ handleFlagUsage(annotationNode, ConfigurationKeys.ALL_ARGS_CONSTRUCTOR_FLAG_USAGE, "@AllArgsConstructor", ConfigurationKeys.ANY_CONSTRUCTOR_FLAG_USAGE, "any @xArgsConstructor");
+
deleteAnnotationIfNeccessary(annotationNode, AllArgsConstructor.class);
deleteImportFromCompilationUnit(annotationNode, "lombok.AccessLevel");
JavacNode typeNode = annotationNode.up();
@@ -234,8 +241,8 @@ public class HandleConstructor {
JCVariableDecl field = (JCVariableDecl) fieldNode.get();
Name fieldName = removePrefixFromField(fieldNode);
Name rawName = field.name;
- List<JCAnnotation> nonNulls = findAnnotations(fieldNode, TransformationsUtil.NON_NULL_PATTERN);
- List<JCAnnotation> nullables = findAnnotations(fieldNode, TransformationsUtil.NULLABLE_PATTERN);
+ List<JCAnnotation> nonNulls = findAnnotations(fieldNode, NON_NULL_PATTERN);
+ List<JCAnnotation> nullables = findAnnotations(fieldNode, NULLABLE_PATTERN);
long flags = JavacHandlerUtil.addFinalIfNeeded(Flags.PARAMETER, typeNode.getContext());
JCVariableDecl param = maker.VarDef(maker.Modifiers(flags, nonNulls.appendList(nullables)), fieldName, field.vartype, null);
params.append(param);
@@ -297,8 +304,8 @@ public class HandleConstructor {
JCVariableDecl field = (JCVariableDecl) fieldNode.get();
Name fieldName = removePrefixFromField(fieldNode);
JCExpression pType = cloneType(maker, field.vartype, source, typeNode.getContext());
- List<JCAnnotation> nonNulls = findAnnotations(fieldNode, TransformationsUtil.NON_NULL_PATTERN);
- List<JCAnnotation> nullables = findAnnotations(fieldNode, TransformationsUtil.NULLABLE_PATTERN);
+ List<JCAnnotation> nonNulls = findAnnotations(fieldNode, NON_NULL_PATTERN);
+ List<JCAnnotation> nullables = findAnnotations(fieldNode, NULLABLE_PATTERN);
long flags = JavacHandlerUtil.addFinalIfNeeded(Flags.PARAMETER, typeNode.getContext());
JCVariableDecl param = maker.VarDef(maker.Modifiers(flags, nonNulls.appendList(nullables)), fieldName, pType, null);
params.append(param);
diff --git a/src/core/lombok/javac/handlers/HandleData.java b/src/core/lombok/javac/handlers/HandleData.java
index 858fb543..9ecf8754 100644
--- a/src/core/lombok/javac/handlers/HandleData.java
+++ b/src/core/lombok/javac/handlers/HandleData.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009-2011 The Project Lombok Authors.
+ * Copyright (C) 2009-2014 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
@@ -21,8 +21,10 @@
*/
package lombok.javac.handlers;
+import static lombok.core.handlers.HandlerUtil.*;
import static lombok.javac.handlers.JavacHandlerUtil.*;
import lombok.AccessLevel;
+import lombok.ConfigurationKeys;
import lombok.Data;
import lombok.core.AnnotationValues;
import lombok.javac.JavacAnnotationHandler;
@@ -39,6 +41,8 @@ import com.sun.tools.javac.tree.JCTree.JCAnnotation;
@ProviderFor(JavacAnnotationHandler.class)
public class HandleData extends JavacAnnotationHandler<Data> {
@Override public void handle(AnnotationValues<Data> annotation, JCAnnotation ast, JavacNode annotationNode) {
+ handleFlagUsage(annotationNode, ConfigurationKeys.DATA_FLAG_USAGE, "@Data");
+
deleteAnnotationIfNeccessary(annotationNode, Data.class);
JavacNode typeNode = annotationNode.up();
boolean notAClass = !isClass(typeNode);
diff --git a/src/core/lombok/javac/handlers/HandleDelegate.java b/src/core/lombok/javac/handlers/HandleDelegate.java
index 5e603777..ec6ea20c 100644
--- a/src/core/lombok/javac/handlers/HandleDelegate.java
+++ b/src/core/lombok/javac/handlers/HandleDelegate.java
@@ -21,6 +21,7 @@
*/
package lombok.javac.handlers;
+import static lombok.core.handlers.HandlerUtil.*;
import static lombok.javac.handlers.JavacHandlerUtil.*;
import static com.sun.tools.javac.code.Flags.*;
@@ -40,6 +41,7 @@ import javax.lang.model.type.ExecutableType;
import javax.lang.model.type.TypeKind;
import javax.lang.model.type.TypeMirror;
+import lombok.ConfigurationKeys;
import lombok.Delegate;
import lombok.core.AST.Kind;
import lombok.core.AnnotationValues;
@@ -97,6 +99,8 @@ public class HandleDelegate extends JavacAnnotationHandler<Delegate> {
private static final String LEGALITY_OF_DELEGATE = "@Delegate is legal only on instance fields or no-argument instance methods.";
@Override public void handle(AnnotationValues<Delegate> annotation, JCAnnotation ast, JavacNode annotationNode) {
+ handleFlagUsage(annotationNode, ConfigurationKeys.DELEGATE_FLAG_USAGE, "@Delegate");
+
deleteAnnotationIfNeccessary(annotationNode, Delegate.class);
Type delegateType;
diff --git a/src/core/lombok/javac/handlers/HandleEqualsAndHashCode.java b/src/core/lombok/javac/handlers/HandleEqualsAndHashCode.java
index 05c07c7a..2c998f48 100644
--- a/src/core/lombok/javac/handlers/HandleEqualsAndHashCode.java
+++ b/src/core/lombok/javac/handlers/HandleEqualsAndHashCode.java
@@ -21,6 +21,7 @@
*/
package lombok.javac.handlers;
+import static lombok.core.handlers.HandlerUtil.*;
import static lombok.javac.Javac.*;
import static lombok.javac.handlers.JavacHandlerUtil.*;
@@ -28,6 +29,7 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
+import lombok.ConfigurationKeys;
import lombok.EqualsAndHashCode;
import lombok.core.AST.Kind;
import lombok.core.AnnotationValues;
@@ -85,6 +87,8 @@ public class HandleEqualsAndHashCode extends JavacAnnotationHandler<EqualsAndHas
}
@Override public void handle(AnnotationValues<EqualsAndHashCode> annotation, JCAnnotation ast, JavacNode annotationNode) {
+ handleFlagUsage(annotationNode, ConfigurationKeys.EQUALS_AND_HASH_CODE_FLAG_USAGE, "@EqualsAndHashCode");
+
deleteAnnotationIfNeccessary(annotationNode, EqualsAndHashCode.class);
EqualsAndHashCode ann = annotation.getInstance();
List<String> excludes = List.from(ann.exclude());
diff --git a/src/core/lombok/javac/handlers/HandleExtensionMethod.java b/src/core/lombok/javac/handlers/HandleExtensionMethod.java
index 3aee2f51..345c5f8e 100644
--- a/src/core/lombok/javac/handlers/HandleExtensionMethod.java
+++ b/src/core/lombok/javac/handlers/HandleExtensionMethod.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012 The Project Lombok Authors.
+ * Copyright (C) 2012-2014 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
@@ -22,6 +22,7 @@
package lombok.javac.handlers;
import static com.sun.tools.javac.code.Flags.*;
+import static lombok.core.handlers.HandlerUtil.*;
import static lombok.javac.handlers.JavacHandlerUtil.*;
import static lombok.javac.handlers.JavacResolver.*;
@@ -30,6 +31,7 @@ import java.util.List;
import javax.lang.model.element.ElementKind;
+import lombok.ConfigurationKeys;
import lombok.core.AnnotationValues;
import lombok.core.HandlerPriority;
import lombok.experimental.ExtensionMethod;
@@ -64,6 +66,8 @@ import com.sun.tools.javac.tree.JCTree.JCMethodInvocation;
public class HandleExtensionMethod extends JavacAnnotationHandler<ExtensionMethod> {
@Override
public void handle(final AnnotationValues<ExtensionMethod> annotation, final JCAnnotation source, final JavacNode annotationNode) {
+ handleExperimentalFlagUsage(annotationNode, ConfigurationKeys.EXTENSION_METHOD_FLAG_USAGE, "@ExtensionMethod");
+
deleteAnnotationIfNeccessary(annotationNode, ExtensionMethod.class);
JavacNode typeNode = annotationNode.up();
boolean isClassOrEnum = isClassOrEnum(typeNode);
diff --git a/src/core/lombok/javac/handlers/HandleFieldDefaults.java b/src/core/lombok/javac/handlers/HandleFieldDefaults.java
index 038f3e3f..335ab1fe 100644
--- a/src/core/lombok/javac/handlers/HandleFieldDefaults.java
+++ b/src/core/lombok/javac/handlers/HandleFieldDefaults.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012 The Project Lombok Authors.
+ * Copyright (C) 2012-2014 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
@@ -21,8 +21,10 @@
*/
package lombok.javac.handlers;
+import static lombok.core.handlers.HandlerUtil.*;
import static lombok.javac.handlers.JavacHandlerUtil.*;
import lombok.AccessLevel;
+import lombok.ConfigurationKeys;
import lombok.core.AST.Kind;
import lombok.core.AnnotationValues;
import lombok.core.HandlerPriority;
@@ -96,6 +98,8 @@ public class HandleFieldDefaults extends JavacAnnotationHandler<FieldDefaults> {
}
@Override public void handle(AnnotationValues<FieldDefaults> annotation, JCAnnotation ast, JavacNode annotationNode) {
+ handleExperimentalFlagUsage(annotationNode, ConfigurationKeys.FIELD_DEFAULTS_FLAG_USAGE, "@FieldDefaults");
+
deleteAnnotationIfNeccessary(annotationNode, FieldDefaults.class);
deleteImportFromCompilationUnit(annotationNode, "lombok.AccessLevel");
JavacNode node = annotationNode.up();
diff --git a/src/core/lombok/javac/handlers/HandleGetter.java b/src/core/lombok/javac/handlers/HandleGetter.java
index 6b055193..48a13bde 100644
--- a/src/core/lombok/javac/handlers/HandleGetter.java
+++ b/src/core/lombok/javac/handlers/HandleGetter.java
@@ -21,6 +21,7 @@
*/
package lombok.javac.handlers;
+import static lombok.core.handlers.HandlerUtil.*;
import static lombok.javac.Javac.*;
import static lombok.javac.JavacTreeMaker.TypeTag.*;
import static lombok.javac.handlers.JavacHandlerUtil.*;
@@ -31,11 +32,11 @@ import java.util.HashMap;
import java.util.Map;
import lombok.AccessLevel;
+import lombok.ConfigurationKeys;
import lombok.Delegate;
import lombok.Getter;
import lombok.core.AST.Kind;
import lombok.core.AnnotationValues;
-import lombok.core.TransformationsUtil;
import lombok.javac.JavacAnnotationHandler;
import lombok.javac.JavacNode;
import lombok.javac.JavacTreeMaker;
@@ -127,6 +128,8 @@ public class HandleGetter extends JavacAnnotationHandler<Getter> {
}
@Override public void handle(AnnotationValues<Getter> annotation, JCAnnotation ast, JavacNode annotationNode) {
+ handleFlagUsage(annotationNode, ConfigurationKeys.GETTER_FLAG_USAGE, "@Getter");
+
Collection<JavacNode> fields = annotationNode.upFromAnnotationToFields();
deleteAnnotationIfNeccessary(annotationNode, Getter.class);
deleteImportFromCompilationUnit(annotationNode, "lombok.AccessLevel");
@@ -239,8 +242,8 @@ public class HandleGetter extends JavacAnnotationHandler<Getter> {
List<JCExpression> throwsClauses = List.nil();
JCExpression annotationMethodDefaultValue = null;
- List<JCAnnotation> nonNulls = findAnnotations(field, TransformationsUtil.NON_NULL_PATTERN);
- List<JCAnnotation> nullables = findAnnotations(field, TransformationsUtil.NULLABLE_PATTERN);
+ List<JCAnnotation> nonNulls = findAnnotations(field, NON_NULL_PATTERN);
+ List<JCAnnotation> nullables = findAnnotations(field, NULLABLE_PATTERN);
List<JCAnnotation> delegates = findDelegatesAndRemoveFromField(field);
diff --git a/src/core/lombok/javac/handlers/HandleLog.java b/src/core/lombok/javac/handlers/HandleLog.java
index 36f3bbb5..ee7268f7 100644
--- a/src/core/lombok/javac/handlers/HandleLog.java
+++ b/src/core/lombok/javac/handlers/HandleLog.java
@@ -21,10 +21,12 @@
*/
package lombok.javac.handlers;
+import static lombok.core.handlers.HandlerUtil.*;
import static lombok.javac.handlers.JavacHandlerUtil.*;
import java.lang.annotation.Annotation;
+import lombok.ConfigurationKeys;
import lombok.core.AnnotationValues;
import lombok.javac.JavacAnnotationHandler;
import lombok.javac.JavacNode;
@@ -48,24 +50,28 @@ public class HandleLog {
throw new UnsupportedOperationException();
}
- public static void processAnnotation(LoggingFramework framework, AnnotationValues<?> annotation, JavacNode annotationNode, String loggerCategory) {
+ public static void processAnnotation(LoggingFramework framework, AnnotationValues<?> annotation, JavacNode annotationNode, String loggerTopic) {
deleteAnnotationIfNeccessary(annotationNode, framework.getAnnotationClass());
JavacNode typeNode = annotationNode.up();
switch (typeNode.getKind()) {
case TYPE:
- if ((((JCClassDecl)typeNode.get()).mods.flags & Flags.INTERFACE)!= 0) {
+ String 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));
+
+ if ((((JCClassDecl)typeNode.get()).mods.flags & Flags.INTERFACE) != 0) {
annotationNode.addError("@Log is legal only on classes and enums.");
return;
}
-
- if (fieldExists("log", typeNode)!= MemberExistsResult.NOT_EXISTS) {
- annotationNode.addWarning("Field 'log' already exists.");
+ if (fieldExists(logFieldName, typeNode) != MemberExistsResult.NOT_EXISTS) {
+ annotationNode.addWarning("Field '" + logFieldName + "' already exists.");
return;
}
JCFieldAccess loggingType = selfType(typeNode);
- createField(framework, typeNode, loggingType, annotationNode.get(), loggerCategory);
+ createField(framework, typeNode, loggingType, annotationNode.get(), logFieldName, useStatic, loggerTopic);
break;
default:
annotationNode.addError("@Log is legal only on types.");
@@ -79,7 +85,7 @@ public class HandleLog {
return maker.Select(maker.Ident(name), typeNode.toName("class"));
}
- public static boolean createField(LoggingFramework framework, JavacNode typeNode, JCFieldAccess loggingType, JCTree source, String loggerCategory) {
+ private static boolean createField(LoggingFramework framework, JavacNode typeNode, JCFieldAccess loggingType, JCTree source, String logFieldName, boolean useStatic, String loggerTopic) {
JavacTreeMaker maker = typeNode.getTreeMaker();
// private static final <loggerType> log = <factoryMethod>(<parameter>);
@@ -87,17 +93,17 @@ public class HandleLog {
JCExpression factoryMethod = chainDotsString(typeNode, framework.getLoggerFactoryMethodName());
JCExpression loggerName;
- if (loggerCategory == null || loggerCategory.trim().length() == 0) {
+ if (loggerTopic == null || loggerTopic.trim().length() == 0) {
loggerName = framework.createFactoryParameter(typeNode, loggingType);
} else {
- loggerName = maker.Literal(loggerCategory);
+ loggerName = maker.Literal(loggerTopic);
}
JCMethodInvocation factoryMethodCall = maker.Apply(List.<JCExpression>nil(), factoryMethod, List.<JCExpression>of(loggerName));
JCVariableDecl fieldDecl = recursiveSetGeneratedBy(maker.VarDef(
- maker.Modifiers(Flags.PRIVATE | Flags.FINAL | Flags.STATIC),
- typeNode.toName("log"), loggerType, factoryMethodCall), source, typeNode.getContext());
+ maker.Modifiers(Flags.PRIVATE | Flags.FINAL | (useStatic ? Flags.STATIC : 0)),
+ typeNode.toName(logFieldName), loggerType, factoryMethodCall), source, typeNode.getContext());
injectFieldSuppressWarnings(typeNode, fieldDecl);
return true;
@@ -109,6 +115,7 @@ public class HandleLog {
@ProviderFor(JavacAnnotationHandler.class)
public static class HandleCommonsLog extends JavacAnnotationHandler<lombok.extern.apachecommons.CommonsLog> {
@Override public void handle(AnnotationValues<lombok.extern.apachecommons.CommonsLog> annotation, JCAnnotation ast, JavacNode annotationNode) {
+ handleFlagUsage(annotationNode, ConfigurationKeys.LOG_COMMONS_FLAG_USAGE, "@apachecommons.CommonsLog", ConfigurationKeys.LOG_ANY_FLAG_USAGE, "any @Log");
processAnnotation(LoggingFramework.COMMONS, annotation, annotationNode, annotation.getInstance().topic());
}
}
@@ -119,6 +126,7 @@ public class HandleLog {
@ProviderFor(JavacAnnotationHandler.class)
public static class HandleJulLog extends JavacAnnotationHandler<lombok.extern.java.Log> {
@Override public void handle(AnnotationValues<lombok.extern.java.Log> annotation, JCAnnotation ast, JavacNode annotationNode) {
+ handleFlagUsage(annotationNode, ConfigurationKeys.LOG_JUL_FLAG_USAGE, "@java.Log", ConfigurationKeys.LOG_ANY_FLAG_USAGE, "any @Log");
processAnnotation(LoggingFramework.JUL, annotation, annotationNode, annotation.getInstance().topic());
}
}
@@ -129,6 +137,7 @@ public class HandleLog {
@ProviderFor(JavacAnnotationHandler.class)
public static class HandleLog4jLog extends JavacAnnotationHandler<lombok.extern.log4j.Log4j> {
@Override public void handle(AnnotationValues<lombok.extern.log4j.Log4j> annotation, JCAnnotation ast, JavacNode annotationNode) {
+ handleFlagUsage(annotationNode, ConfigurationKeys.LOG_LOG4J_FLAG_USAGE, "@Log4j", ConfigurationKeys.LOG_ANY_FLAG_USAGE, "any @Log");
processAnnotation(LoggingFramework.LOG4J, annotation, annotationNode, annotation.getInstance().topic());
}
}
@@ -139,6 +148,7 @@ public class HandleLog {
@ProviderFor(JavacAnnotationHandler.class)
public static class HandleLog4j2Log extends JavacAnnotationHandler<lombok.extern.log4j.Log4j2> {
@Override public void handle(AnnotationValues<lombok.extern.log4j.Log4j2> annotation, JCAnnotation ast, JavacNode annotationNode) {
+ handleFlagUsage(annotationNode, ConfigurationKeys.LOG_LOG4J2_FLAG_USAGE, "@Log4j2", ConfigurationKeys.LOG_ANY_FLAG_USAGE, "any @Log");
processAnnotation(LoggingFramework.LOG4J2, annotation, annotationNode, annotation.getInstance().topic());
}
}
@@ -149,6 +159,7 @@ public class HandleLog {
@ProviderFor(JavacAnnotationHandler.class)
public static class HandleSlf4jLog extends JavacAnnotationHandler<lombok.extern.slf4j.Slf4j> {
@Override public void handle(AnnotationValues<lombok.extern.slf4j.Slf4j> annotation, JCAnnotation ast, JavacNode annotationNode) {
+ handleFlagUsage(annotationNode, ConfigurationKeys.LOG_SLF4J_FLAG_USAGE, "@Slf4j", ConfigurationKeys.LOG_ANY_FLAG_USAGE, "any @Log");
processAnnotation(LoggingFramework.SLF4J, annotation, annotationNode, annotation.getInstance().topic());
}
}
@@ -159,6 +170,7 @@ public class HandleLog {
@ProviderFor(JavacAnnotationHandler.class)
public static class HandleXSlf4jLog extends JavacAnnotationHandler<lombok.extern.slf4j.XSlf4j> {
@Override public void handle(AnnotationValues<lombok.extern.slf4j.XSlf4j> annotation, JCAnnotation ast, JavacNode annotationNode) {
+ handleFlagUsage(annotationNode, ConfigurationKeys.LOG_XSLF4J_FLAG_USAGE, "@XSlf4j", ConfigurationKeys.LOG_ANY_FLAG_USAGE, "any @Log");
processAnnotation(LoggingFramework.XSLF4J, annotation, annotationNode, annotation.getInstance().topic());
}
}
diff --git a/src/core/lombok/javac/handlers/HandleNonNull.java b/src/core/lombok/javac/handlers/HandleNonNull.java
index 4cab48cf..172e70b3 100644
--- a/src/core/lombok/javac/handlers/HandleNonNull.java
+++ b/src/core/lombok/javac/handlers/HandleNonNull.java
@@ -21,6 +21,7 @@
*/
package lombok.javac.handlers;
+import static lombok.core.handlers.HandlerUtil.*;
import static lombok.javac.Javac.*;
import static lombok.javac.handlers.JavacHandlerUtil.*;
@@ -42,6 +43,7 @@ import com.sun.tools.javac.tree.JCTree.JCTry;
import com.sun.tools.javac.tree.JCTree.JCVariableDecl;
import com.sun.tools.javac.util.List;
+import lombok.ConfigurationKeys;
import lombok.NonNull;
import lombok.core.AnnotationValues;
import lombok.core.HandlerPriority;
@@ -55,6 +57,8 @@ import static lombok.javac.JavacTreeMaker.TreeTag.*;
@HandlerPriority(value = 512) // 2^9; onParameter=@__(@NonNull) has to run first.
public class HandleNonNull extends JavacAnnotationHandler<NonNull> {
@Override public void handle(AnnotationValues<NonNull> annotation, JCAnnotation ast, JavacNode annotationNode) {
+ handleFlagUsage(annotationNode, ConfigurationKeys.NON_NULL_FLAG_USAGE, "@NonNull");
+
if (annotationNode.up().getKind() == Kind.FIELD) {
// This is meaningless unless the field is used to generate a method (@Setter, @RequiredArgsConstructor, etc),
// but in that case those handlers will take care of it. However, we DO check if the annotation is applied to
diff --git a/src/core/lombok/javac/handlers/HandlePrintAST.java b/src/core/lombok/javac/handlers/HandlePrintAST.java
index 7b6d942c..2c229f2b 100644
--- a/src/core/lombok/javac/handlers/HandlePrintAST.java
+++ b/src/core/lombok/javac/handlers/HandlePrintAST.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009-2011 The Project Lombok Authors.
+ * Copyright (C) 2009-2014 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
@@ -52,6 +52,16 @@ public class HandlePrintAST extends JavacAnnotationHandler<PrintAST> {
Lombok.sneakyThrow(e);
}
- annotationNode.up().traverse(new JavacASTVisitor.Printer(annotation.getInstance().printContent(), stream));
+ try {
+ annotationNode.up().traverse(new JavacASTVisitor.Printer(annotation.getInstance().printContent(), stream));
+ } finally {
+ if (stream != System.out) {
+ try {
+ stream.close();
+ } catch (Exception e) {
+ Lombok.sneakyThrow(e);
+ }
+ }
+ }
}
}
diff --git a/src/core/lombok/javac/handlers/HandleSetter.java b/src/core/lombok/javac/handlers/HandleSetter.java
index ae8741de..fbc9ef46 100644
--- a/src/core/lombok/javac/handlers/HandleSetter.java
+++ b/src/core/lombok/javac/handlers/HandleSetter.java
@@ -22,15 +22,16 @@
package lombok.javac.handlers;
import static lombok.javac.Javac.*;
+import static lombok.core.handlers.HandlerUtil.*;
import static lombok.javac.handlers.JavacHandlerUtil.*;
import java.util.Collection;
import lombok.AccessLevel;
+import lombok.ConfigurationKeys;
import lombok.Setter;
import lombok.core.AST.Kind;
import lombok.core.AnnotationValues;
-import lombok.core.TransformationsUtil;
import lombok.javac.Javac;
import lombok.javac.JavacAnnotationHandler;
import lombok.javac.JavacNode;
@@ -118,6 +119,8 @@ public class HandleSetter extends JavacAnnotationHandler<Setter> {
}
@Override public void handle(AnnotationValues<Setter> annotation, JCAnnotation ast, JavacNode annotationNode) {
+ handleFlagUsage(annotationNode, ConfigurationKeys.SETTER_FLAG_USAGE, "@Setter");
+
Collection<JavacNode> fields = annotationNode.upFromAnnotationToFields();
deleteAnnotationIfNeccessary(annotationNode, Setter.class);
deleteImportFromCompilationUnit(annotationNode, "lombok.AccessLevel");
@@ -205,8 +208,8 @@ public class HandleSetter extends JavacAnnotationHandler<Setter> {
JCAssign assign = treeMaker.Assign(fieldRef, treeMaker.Ident(fieldDecl.name));
ListBuffer<JCStatement> statements = new ListBuffer<JCStatement>();
- List<JCAnnotation> nonNulls = findAnnotations(field, TransformationsUtil.NON_NULL_PATTERN);
- List<JCAnnotation> nullables = findAnnotations(field, TransformationsUtil.NULLABLE_PATTERN);
+ List<JCAnnotation> nonNulls = findAnnotations(field, NON_NULL_PATTERN);
+ List<JCAnnotation> nullables = findAnnotations(field, NULLABLE_PATTERN);
Name methodName = field.toName(setterName);
List<JCAnnotation> annsOnParam = copyAnnotations(onParam).appendList(nonNulls).appendList(nullables);
diff --git a/src/core/lombok/javac/handlers/HandleSneakyThrows.java b/src/core/lombok/javac/handlers/HandleSneakyThrows.java
index aa0c3c7e..ffe37a4c 100644
--- a/src/core/lombok/javac/handlers/HandleSneakyThrows.java
+++ b/src/core/lombok/javac/handlers/HandleSneakyThrows.java
@@ -21,12 +21,14 @@
*/
package lombok.javac.handlers;
+import static lombok.core.handlers.HandlerUtil.*;
import static lombok.javac.handlers.JavacHandlerUtil.*;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
+import lombok.ConfigurationKeys;
import lombok.SneakyThrows;
import lombok.core.AnnotationValues;
import lombok.core.HandlerPriority;
@@ -57,6 +59,8 @@ import lombok.javac.Javac;
@HandlerPriority(value = 1024) // 2^10; @NonNull must have run first, so that we wrap around the statements generated by it.
public class HandleSneakyThrows extends JavacAnnotationHandler<SneakyThrows> {
@Override public void handle(AnnotationValues<SneakyThrows> annotation, JCAnnotation ast, JavacNode annotationNode) {
+ handleFlagUsage(annotationNode, ConfigurationKeys.SNEAKY_THROWS_FLAG_USAGE, "@SneakyThrows");
+
deleteAnnotationIfNeccessary(annotationNode, SneakyThrows.class);
Collection<String> exceptionNames = annotation.getRawExpressions("value");
if (exceptionNames.isEmpty()) {
diff --git a/src/core/lombok/javac/handlers/HandleSynchronized.java b/src/core/lombok/javac/handlers/HandleSynchronized.java
index 13b8ffcb..fb6678e6 100644
--- a/src/core/lombok/javac/handlers/HandleSynchronized.java
+++ b/src/core/lombok/javac/handlers/HandleSynchronized.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009-2013 The Project Lombok Authors.
+ * Copyright (C) 2009-2014 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
@@ -21,8 +21,10 @@
*/
package lombok.javac.handlers;
+import static lombok.core.handlers.HandlerUtil.*;
import static lombok.javac.Javac.*;
import static lombok.javac.handlers.JavacHandlerUtil.*;
+import lombok.ConfigurationKeys;
import lombok.Synchronized;
import lombok.core.AST.Kind;
import lombok.core.AnnotationValues;
@@ -54,6 +56,8 @@ public class HandleSynchronized extends JavacAnnotationHandler<Synchronized> {
private static final String STATIC_LOCK_NAME = "$LOCK";
@Override public void handle(AnnotationValues<Synchronized> annotation, JCAnnotation ast, JavacNode annotationNode) {
+ handleFlagUsage(annotationNode, ConfigurationKeys.SYNCHRONIZED_FLAG_USAGE, "@Synchronized");
+
if (inNetbeansEditor(annotationNode)) return;
deleteAnnotationIfNeccessary(annotationNode, Synchronized.class);
diff --git a/src/core/lombok/javac/handlers/HandleToString.java b/src/core/lombok/javac/handlers/HandleToString.java
index f1edae0c..743e7b26 100644
--- a/src/core/lombok/javac/handlers/HandleToString.java
+++ b/src/core/lombok/javac/handlers/HandleToString.java
@@ -21,11 +21,13 @@
*/
package lombok.javac.handlers;
+import static lombok.core.handlers.HandlerUtil.*;
import static lombok.javac.handlers.JavacHandlerUtil.*;
import static lombok.javac.Javac.*;
import java.util.Collection;
+import lombok.ConfigurationKeys;
import lombok.ToString;
import lombok.core.AnnotationValues;
import lombok.core.AST.Kind;
@@ -71,6 +73,8 @@ public class HandleToString extends JavacAnnotationHandler<ToString> {
}
@Override public void handle(AnnotationValues<ToString> annotation, JCAnnotation ast, JavacNode annotationNode) {
+ handleFlagUsage(annotationNode, ConfigurationKeys.TO_STRING_FLAG_USAGE, "@ToString");
+
deleteAnnotationIfNeccessary(annotationNode, ToString.class);
ToString ann = annotation.getInstance();
@@ -91,9 +95,14 @@ public class HandleToString extends JavacAnnotationHandler<ToString> {
annotation.setWarning("exclude", "exclude and of are mutually exclusive; the 'exclude' parameter will be ignored.");
}
- FieldAccess fieldAccess = ann.doNotUseGetters() ? FieldAccess.PREFER_FIELD : FieldAccess.GETTER;
+ Boolean doNotUseGettersConfiguration = annotationNode.getAst().readConfiguration(ConfigurationKeys.TO_STRING_DO_NOT_USE_GETTERS);
+ boolean doNotUseGetters = annotation.isExplicit("doNotUseGetters") || doNotUseGettersConfiguration == null ? ann.doNotUseGetters() : doNotUseGettersConfiguration;
+ FieldAccess fieldAccess = doNotUseGetters ? FieldAccess.PREFER_FIELD : FieldAccess.GETTER;
+
+ Boolean fieldNamesConfiguration = annotationNode.getAst().readConfiguration(ConfigurationKeys.TO_STRING_INCLUDE_FIELD_NAMES);
+ boolean includeFieldNames = annotation.isExplicit("includeFieldNames") || fieldNamesConfiguration == null ? ann.includeFieldNames() : fieldNamesConfiguration;
- generateToString(typeNode, annotationNode, excludes, includes, ann.includeFieldNames(), callSuper, true, fieldAccess);
+ generateToString(typeNode, annotationNode, excludes, includes, includeFieldNames, callSuper, true, fieldAccess);
}
public void generateToStringForType(JavacNode typeNode, JavacNode errorNode) {
@@ -105,7 +114,8 @@ public class HandleToString extends JavacAnnotationHandler<ToString> {
boolean includeFieldNames = true;
try {
- includeFieldNames = ((Boolean)ToString.class.getMethod("includeFieldNames").getDefaultValue()).booleanValue();
+ Boolean configuration = typeNode.getAst().readConfiguration(ConfigurationKeys.TO_STRING_INCLUDE_FIELD_NAMES);
+ includeFieldNames = configuration != null ? configuration : ((Boolean)ToString.class.getMethod("includeFieldNames").getDefaultValue()).booleanValue();
} catch (Exception ignore) {}
generateToString(typeNode, errorNode, null, null, includeFieldNames, null, false, FieldAccess.GETTER);
}
diff --git a/src/core/lombok/javac/handlers/HandleVal.java b/src/core/lombok/javac/handlers/HandleVal.java
index 8dc8e865..75464195 100644
--- a/src/core/lombok/javac/handlers/HandleVal.java
+++ b/src/core/lombok/javac/handlers/HandleVal.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010-2012 The Project Lombok Authors.
+ * Copyright (C) 2010-2014 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
@@ -21,8 +21,9 @@
*/
package lombok.javac.handlers;
+import static lombok.core.handlers.HandlerUtil.*;
import static lombok.javac.handlers.JavacHandlerUtil.*;
-
+import lombok.ConfigurationKeys;
import lombok.val;
import lombok.core.HandlerPriority;
import lombok.javac.JavacASTAdapter;
@@ -55,6 +56,8 @@ public class HandleVal extends JavacASTAdapter {
if (!typeMatches(val.class, localNode, local.vartype)) return;
+ handleFlagUsage(localNode, ConfigurationKeys.VAL_FLAG_USAGE, "val");
+
JCTree parentRaw = localNode.directUp().get();
if (parentRaw instanceof JCForLoop) {
localNode.addError("'val' is not allowed in old-style for loops");
diff --git a/src/core/lombok/javac/handlers/HandleValue.java b/src/core/lombok/javac/handlers/HandleValue.java
index 15fb4781..90f6a98d 100644
--- a/src/core/lombok/javac/handlers/HandleValue.java
+++ b/src/core/lombok/javac/handlers/HandleValue.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012-2013 The Project Lombok Authors.
+ * Copyright (C) 2012-2014 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
@@ -21,11 +21,13 @@
*/
package lombok.javac.handlers;
+import static lombok.core.handlers.HandlerUtil.*;
import static lombok.javac.handlers.JavacHandlerUtil.*;
import java.lang.annotation.Annotation;
import lombok.AccessLevel;
+import lombok.ConfigurationKeys;
import lombok.core.AnnotationValues;
import lombok.core.HandlerPriority;
import lombok.experimental.NonFinal;
@@ -50,6 +52,9 @@ public class HandleValue extends JavacAnnotationHandler<Value> {
@Override public void handle(AnnotationValues<Value> annotation, JCAnnotation ast, JavacNode annotationNode) {
@SuppressWarnings("deprecation")
Class<? extends Annotation> oldExperimentalValue = lombok.experimental.Value.class;
+
+ handleFlagUsage(annotationNode, ConfigurationKeys.VALUE_FLAG_USAGE, "@Value");
+
deleteAnnotationIfNeccessary(annotationNode, Value.class, oldExperimentalValue);
JavacNode typeNode = annotationNode.up();
boolean notAClass = !isClass(typeNode);
diff --git a/src/core/lombok/javac/handlers/HandleWither.java b/src/core/lombok/javac/handlers/HandleWither.java
index f6277bc3..7b55b671 100644
--- a/src/core/lombok/javac/handlers/HandleWither.java
+++ b/src/core/lombok/javac/handlers/HandleWither.java
@@ -21,15 +21,16 @@
*/
package lombok.javac.handlers;
+import static lombok.core.handlers.HandlerUtil.*;
import static lombok.javac.Javac.*;
import static lombok.javac.handlers.JavacHandlerUtil.*;
import java.util.Collection;
import lombok.AccessLevel;
+import lombok.ConfigurationKeys;
import lombok.core.AST.Kind;
import lombok.core.AnnotationValues;
-import lombok.core.TransformationsUtil;
import lombok.experimental.Wither;
import lombok.javac.JavacAnnotationHandler;
import lombok.javac.JavacNode;
@@ -119,6 +120,8 @@ public class HandleWither extends JavacAnnotationHandler<Wither> {
}
@Override public void handle(AnnotationValues<Wither> annotation, JCAnnotation ast, JavacNode annotationNode) {
+ handleExperimentalFlagUsage(annotationNode, ConfigurationKeys.WITHER_FLAG_USAGE, "@Wither");
+
Collection<JavacNode> fields = annotationNode.upFromAnnotationToFields();
deleteAnnotationIfNeccessary(annotationNode, Wither.class);
deleteImportFromCompilationUnit(annotationNode, "lombok.AccessLevel");
@@ -208,8 +211,8 @@ public class HandleWither extends JavacAnnotationHandler<Wither> {
JCVariableDecl fieldDecl = (JCVariableDecl) field.get();
ListBuffer<JCStatement> statements = new ListBuffer<JCStatement>();
- List<JCAnnotation> nonNulls = findAnnotations(field, TransformationsUtil.NON_NULL_PATTERN);
- List<JCAnnotation> nullables = findAnnotations(field, TransformationsUtil.NULLABLE_PATTERN);
+ List<JCAnnotation> nonNulls = findAnnotations(field, NON_NULL_PATTERN);
+ List<JCAnnotation> nullables = findAnnotations(field, NULLABLE_PATTERN);
Name methodName = field.toName(witherName);
List<JCAnnotation> annsOnParam = copyAnnotations(onParam).appendList(nonNulls).appendList(nullables);
diff --git a/src/core/lombok/javac/handlers/JavacHandlerUtil.java b/src/core/lombok/javac/handlers/JavacHandlerUtil.java
index bc4dda8e..37164a6c 100644
--- a/src/core/lombok/javac/handlers/JavacHandlerUtil.java
+++ b/src/core/lombok/javac/handlers/JavacHandlerUtil.java
@@ -21,7 +21,7 @@
*/
package lombok.javac.handlers;
-import static lombok.core.TransformationsUtil.INVALID_ON_BUILDERS;
+import static lombok.core.handlers.HandlerUtil.*;
import static lombok.javac.Javac.*;
import java.lang.annotation.Annotation;
@@ -29,6 +29,7 @@ import java.lang.ref.WeakReference;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.WeakHashMap;
@@ -36,12 +37,13 @@ import java.util.regex.Matcher;
import java.util.regex.Pattern;
import lombok.AccessLevel;
+import lombok.ConfigurationKeys;
import lombok.Data;
import lombok.Getter;
import lombok.core.AST.Kind;
import lombok.core.AnnotationValues;
import lombok.core.AnnotationValues.AnnotationValue;
-import lombok.core.TransformationsUtil;
+import lombok.core.handlers.HandlerUtil;
import lombok.core.TypeResolver;
import lombok.delombok.LombokOptionsFactory;
import lombok.experimental.Accessors;
@@ -391,7 +393,7 @@ public class JavacHandlerUtil {
* Convenient wrapper around {@link TransformationsUtil#toAllGetterNames(lombok.core.AnnotationValues, CharSequence, boolean)}.
*/
public static java.util.List<String> toAllGetterNames(JavacNode field) {
- return TransformationsUtil.toAllGetterNames(getAccessorsForField(field), field.getName(), isBoolean(field));
+ return HandlerUtil.toAllGetterNames(field.getAst(), getAccessorsForField(field), field.getName(), isBoolean(field));
}
/**
@@ -400,7 +402,7 @@ public class JavacHandlerUtil {
* Convenient wrapper around {@link TransformationsUtil#toGetterName(lombok.core.AnnotationValues, CharSequence, boolean)}.
*/
public static String toGetterName(JavacNode field) {
- return TransformationsUtil.toGetterName(getAccessorsForField(field), field.getName(), isBoolean(field));
+ return HandlerUtil.toGetterName(field.getAst(), getAccessorsForField(field), field.getName(), isBoolean(field));
}
/**
@@ -408,7 +410,7 @@ public class JavacHandlerUtil {
* Convenient wrapper around {@link TransformationsUtil#toAllSetterNames(lombok.core.AnnotationValues, CharSequence, boolean)}.
*/
public static java.util.List<String> toAllSetterNames(JavacNode field) {
- return TransformationsUtil.toAllSetterNames(getAccessorsForField(field), field.getName(), isBoolean(field));
+ return HandlerUtil.toAllSetterNames(field.getAst(), getAccessorsForField(field), field.getName(), isBoolean(field));
}
/**
@@ -417,7 +419,7 @@ public class JavacHandlerUtil {
* Convenient wrapper around {@link TransformationsUtil#toSetterName(lombok.core.AnnotationValues, CharSequence, boolean)}.
*/
public static String toSetterName(JavacNode field) {
- return TransformationsUtil.toSetterName(getAccessorsForField(field), field.getName(), isBoolean(field));
+ return HandlerUtil.toSetterName(field.getAst(), getAccessorsForField(field), field.getName(), isBoolean(field));
}
/**
@@ -425,7 +427,7 @@ public class JavacHandlerUtil {
* Convenient wrapper around {@link TransformationsUtil#toAllWitherNames(lombok.core.AnnotationValues, CharSequence, boolean)}.
*/
public static java.util.List<String> toAllWitherNames(JavacNode field) {
- return TransformationsUtil.toAllWitherNames(getAccessorsForField(field), field.getName(), isBoolean(field));
+ return HandlerUtil.toAllWitherNames(field.getAst(), getAccessorsForField(field), field.getName(), isBoolean(field));
}
/**
@@ -434,7 +436,7 @@ public class JavacHandlerUtil {
* Convenient wrapper around {@link TransformationsUtil#toWitherName(lombok.core.AnnotationValues, CharSequence, boolean)}.
*/
public static String toWitherName(JavacNode field) {
- return TransformationsUtil.toWitherName(getAccessorsForField(field), field.getName(), isBoolean(field));
+ return HandlerUtil.toWitherName(field.getAst(), getAccessorsForField(field), field.getName(), isBoolean(field));
}
/**
@@ -446,9 +448,7 @@ public class JavacHandlerUtil {
AnnotationValues<Accessors> accessors = JavacHandlerUtil.getAccessorsForField(field);
- boolean forced = (accessors.getActualExpression("chain") != null);
- Accessors instance = accessors.getInstance();
- return instance.chain() || (instance.fluent() && !forced);
+ return HandlerUtil.shouldReturnThis0(accessors, field.getAst());
}
public static JCExpression cloneSelfType(JavacNode field) {
@@ -481,10 +481,11 @@ public class JavacHandlerUtil {
}
public static Name removePrefixFromField(JavacNode field) {
- String[] prefixes = null;
+ java.util.List<String> prefixes = null;
for (JavacNode node : field.down()) {
if (annotationTypeMatches(Accessors.class, node)) {
- prefixes = createAnnotation(Accessors.class, node).getInstance().prefix();
+ AnnotationValues<Accessors> ann = createAnnotation(Accessors.class, node);
+ if (ann.isExplicit("prefix")) prefixes = Arrays.asList(ann.getInstance().prefix());
break;
}
}
@@ -495,7 +496,8 @@ public class JavacHandlerUtil {
while (current != null) {
for (JavacNode node : current.down()) {
if (annotationTypeMatches(Accessors.class, node)) {
- prefixes = createAnnotation(Accessors.class, node).getInstance().prefix();
+ AnnotationValues<Accessors> ann = createAnnotation(Accessors.class, node);
+ if (ann.isExplicit("prefix")) prefixes = Arrays.asList(ann.getInstance().prefix());
break outer;
}
}
@@ -503,8 +505,10 @@ public class JavacHandlerUtil {
}
}
- if (prefixes != null && prefixes.length > 0) {
- CharSequence newName = TransformationsUtil.removePrefix(field.getName(), prefixes);
+ if (prefixes == null) prefixes = field.getAst().readConfiguration(ConfigurationKeys.ACCESSORS_PREFIX);
+
+ if (!prefixes.isEmpty()) {
+ CharSequence newName = removePrefix(field.getName(), prefixes);
if (newName != null) return field.toName(newName.toString());
}
@@ -1073,11 +1077,20 @@ public class JavacHandlerUtil {
return problematic.toList();
}
- static List<JCAnnotation> unboxAndRemoveAnnotationParameter(JCAnnotation ast, String parameterName, String errorName, JavacNode errorNode) {
+ static List<JCAnnotation> unboxAndRemoveAnnotationParameter(JCAnnotation ast, String parameterName, String errorName, JavacNode annotationNode) {
ListBuffer<JCExpression> params = new ListBuffer<JCExpression>();
ListBuffer<JCAnnotation> result = new ListBuffer<JCAnnotation>();
- errorNode.removeDeferredErrors();
+ try {
+ for (JCExpression arg : ast.args) {
+ String argName = "value";
+ if (arg instanceof JCAssign) {
+ JCAssign as = (JCAssign) arg;
+ argName = as.lhs.toString();
+ }
+ if (!argName.equals(parameterName)) continue;
+ }
+ } catch (Exception ignore) {}
outer:
for (JCExpression param : ast.args) {
@@ -1097,11 +1110,14 @@ public class JavacHandlerUtil {
continue outer;
}
+ int endPos = Javac.getEndPosition(param.pos(), (JCCompilationUnit) annotationNode.top().get());
+ annotationNode.getAst().removeFromDeferredDiagnostics(param.pos, endPos);
+
if (valueOfParam instanceof JCAnnotation) {
String dummyAnnotationName = ((JCAnnotation) valueOfParam).annotationType.toString();
dummyAnnotationName = dummyAnnotationName.replace("_", "").replace("$", "").replace("x", "").replace("X", "");
if (dummyAnnotationName.length() > 0) {
- errorNode.addError("The correct format is " + errorName + "@__({@SomeAnnotation, @SomeOtherAnnotation}))");
+ annotationNode.addError("The correct format is " + errorName + "@__({@SomeAnnotation, @SomeOtherAnnotation}))");
continue outer;
}
for (JCExpression expr : ((JCAnnotation) valueOfParam).args) {
@@ -1110,7 +1126,7 @@ public class JavacHandlerUtil {
if ("value".equals(id.name.toString())) {
expr = ((JCAssign) expr).rhs;
} else {
- errorNode.addError("The correct format is " + errorName + "@__({@SomeAnnotation, @SomeOtherAnnotation}))");
+ annotationNode.addError("The correct format is " + errorName + "@__({@SomeAnnotation, @SomeOtherAnnotation}))");
continue outer;
}
}
@@ -1122,12 +1138,12 @@ public class JavacHandlerUtil {
if (expr2 instanceof JCAnnotation) {
result.append((JCAnnotation) expr2);
} else {
- errorNode.addError("The correct format is " + errorName + "@__({@SomeAnnotation, @SomeOtherAnnotation}))");
+ annotationNode.addError("The correct format is " + errorName + "@__({@SomeAnnotation, @SomeOtherAnnotation}))");
continue outer;
}
}
} else {
- errorNode.addError("The correct format is " + errorName + "@__({@SomeAnnotation, @SomeOtherAnnotation}))");
+ annotationNode.addError("The correct format is " + errorName + "@__({@SomeAnnotation, @SomeOtherAnnotation}))");
continue outer;
}
}
@@ -1135,7 +1151,7 @@ public class JavacHandlerUtil {
if (valueOfParam instanceof JCNewArray && ((JCNewArray) valueOfParam).elems.isEmpty()) {
// Then we just remove it and move on (it's onMethod={} for example).
} else {
- errorNode.addError("The correct format is " + errorName + "@__({@SomeAnnotation, @SomeOtherAnnotation}))");
+ annotationNode.addError("The correct format is " + errorName + "@__({@SomeAnnotation, @SomeOtherAnnotation}))");
}
}
}
diff --git a/src/core/lombok/val.java b/src/core/lombok/val.java
index 7e495c8d..cd8652d6 100644
--- a/src/core/lombok/val.java
+++ b/src/core/lombok/val.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010-2012 The Project Lombok Authors.
+ * Copyright (C) 2010-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
@@ -30,4 +30,5 @@ package lombok;
* <p>
* Complete documentation is found at <a href="http://projectlombok.org/features/val.html">the project lombok features page for &#64;val</a>.
*/
-public @interface val {}
+public @interface val {
+}