diff options
-rw-r--r-- | src/core/lombok/Builder.java | 121 | ||||
-rw-r--r-- | src/core/lombok/core/LombokInternalAliasing.java | 1 | ||||
-rw-r--r-- | src/core/lombok/eclipse/handlers/HandleBuilder.java | 14 | ||||
-rw-r--r-- | src/core/lombok/eclipse/handlers/HandleConstructor.java | 2 | ||||
-rw-r--r-- | src/core/lombok/experimental/Builder.java | 5 | ||||
-rw-r--r-- | src/core/lombok/javac/handlers/HandleBuilder.java | 14 | ||||
-rw-r--r-- | src/core/lombok/javac/handlers/HandleConstructor.java | 2 | ||||
-rw-r--r-- | src/utils/lombok/core/LombokImmutableList.java | 6 |
8 files changed, 158 insertions, 7 deletions
diff --git a/src/core/lombok/Builder.java b/src/core/lombok/Builder.java new file mode 100644 index 00000000..9cbd2d58 --- /dev/null +++ b/src/core/lombok/Builder.java @@ -0,0 +1,121 @@ +/* + * 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 static java.lang.annotation.ElementType.*; +import static java.lang.annotation.RetentionPolicy.*; + +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +/** + * The builder annotation creates a so-called 'builder' aspect to the class that is annotated or the class + * that contains a member which is annotated with {@code @Builder}. + * <p> + * If a member is annotated, it must be either a constructor or a static method. If a class is annotated, + * then a private constructor is generated with all fields as arguments + * (as if {@code @AllArgsConstructor(AccessLevel.PRIVATE)} is present + * on the class), and it is as if this constructor has been annotated with {@code @Builder} instead. + * <p> + * The effect of {@code @Builder} is that an inner class is generated named <code><strong>T</strong>Builder</code>, + * with a private constructor. Instances of <code><strong>T</strong>Builder</code> are made with the static + * method named {@code builder()} which is also generated for you in the class itself (not in the builder class). + * <p> + * The <code><strong>T</strong>Builder</code> class contains 1 method for each parameter of the annotated + * constructor / static method (each field, when annotating a class), which returns the builder itself. + * The builder also has a <code>build()</code> method which returns a completed instance of the original type, + * created by passing all parameters as set via the various other methods in the builder to the constructor + * or static method that was annotated with {@code @Builder}. The return type of this method will be the same + * as the relevant class, unless a static method has been annotated, in which case it'll be equal to the + * return type of that method. + * <p> + * Complete documentation is found at <a href="http://projectlombok.org/features/experimental/Builder.html">the project lombok features page for @Builder</a>. + * <p> + * <p> + * Before: + * + * <pre> + * @Builder + * class Example { + * private int foo; + * private final String bar; + * } + * </pre> + * + * After: + * + * <pre> + * class Example<T> { + * private T foo; + * private final String bar; + * + * private Example(T foo, String bar) { + * this.foo = foo; + * this.bar = bar; + * } + * + * public static <T> ExampleBuilder<T> builder() { + * return new ExampleBuilder<T>(); + * } + * + * public static class ExampleBuilder<T> { + * private T foo; + * private String bar; + * + * private ExampleBuilder() {} + * + * public ExampleBuilder foo(T foo) { + * this.foo = foo; + * return this; + * } + * + * public ExampleBuilder bar(String bar) { + * this.bar = bar; + * return this; + * } + * + * @java.lang.Override public String toString() { + * return "ExampleBuilder(foo = " + foo + ", bar = " + bar + ")"; + * } + * + * public Example build() { + * return new Example(foo, bar); + * } + * } + * } + * </pre> + */ +@Target({TYPE, METHOD, CONSTRUCTOR}) +@Retention(SOURCE) +public @interface Builder { + /** Name of the static method that creates a new builder instance. Default: {@code builder}. */ + String builderMethodName() default "builder"; + + /** Name of the instance method in the builder class that creates an instance of your {@code @Builder}-annotated class. */ + String buildMethodName() default "build"; + + /** Name of the builder class. + * Default for {@code @Builder} on types and constructors: {@code (TypeName)Builder}. + * Default for {@code @Builder} on static methods: {@code (ReturnTypeName)Builder}. + */ + String builderClassName() default ""; +} diff --git a/src/core/lombok/core/LombokInternalAliasing.java b/src/core/lombok/core/LombokInternalAliasing.java index 8d6794ae..08764a5c 100644 --- a/src/core/lombok/core/LombokInternalAliasing.java +++ b/src/core/lombok/core/LombokInternalAliasing.java @@ -50,6 +50,7 @@ public class LombokInternalAliasing { Map<String, String> m2 = new HashMap<String, String>(); m2.put("lombok.experimental.Value", "lombok.Value"); + m2.put("lombok.experimental.Builder", "lombok.Builder"); m2.put("lombok.Delegate", "lombok.experimental.Delegate"); ALIASES = Collections.unmodifiableMap(m2); } diff --git a/src/core/lombok/eclipse/handlers/HandleBuilder.java b/src/core/lombok/eclipse/handlers/HandleBuilder.java index 522501f6..80f80ddd 100644 --- a/src/core/lombok/eclipse/handlers/HandleBuilder.java +++ b/src/core/lombok/eclipse/handlers/HandleBuilder.java @@ -56,6 +56,7 @@ import org.eclipse.jdt.internal.compiler.lookup.TypeConstants; import org.mangosdk.spi.ProviderFor; import lombok.AccessLevel; +import lombok.Builder; import lombok.ConfigurationKeys; import lombok.core.AST.Kind; import lombok.core.AnnotationValues; @@ -64,18 +65,27 @@ import lombok.eclipse.Eclipse; import lombok.eclipse.EclipseAnnotationHandler; import lombok.eclipse.EclipseNode; import lombok.eclipse.handlers.HandleConstructor.SkipIfConstructorExists; -import lombok.experimental.Builder; import lombok.experimental.NonFinal; @ProviderFor(EclipseAnnotationHandler.class) @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> { + private static final boolean toBoolean(Object expr, boolean defaultValue) { + if (expr == null) return defaultValue; + return ((Boolean) expr).booleanValue(); + } + @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(); + + // These exist just to support the 'old' lombok.experimental.Builder, which had these properties. lombok.Builder no longer has them. + boolean fluent = toBoolean(annotation.getActualExpression("fluent"), true); + boolean chain = toBoolean(annotation.getActualExpression("chain"), true); + String builderMethodName = builderInstance.builderMethodName(); String buildMethodName = builderInstance.buildMethodName(); String builderClassName = builderInstance.builderClassName(); @@ -205,7 +215,7 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> { List<EclipseNode> fieldNodes = addFieldsToBuilder(builderType, namesOfParameters, typesOfParameters, ast); List<AbstractMethodDeclaration> newMethods = new ArrayList<AbstractMethodDeclaration>(); for (EclipseNode fieldNode : fieldNodes) { - MethodDeclaration newMethod = makeSetterMethodForBuilder(builderType, fieldNode, annotationNode, builderInstance.fluent(), builderInstance.chain()); + MethodDeclaration newMethod = makeSetterMethodForBuilder(builderType, fieldNode, annotationNode, fluent, chain); if (newMethod != null) newMethods.add(newMethod); } diff --git a/src/core/lombok/eclipse/handlers/HandleConstructor.java b/src/core/lombok/eclipse/handlers/HandleConstructor.java index b72d000f..d19e95e4 100644 --- a/src/core/lombok/eclipse/handlers/HandleConstructor.java +++ b/src/core/lombok/eclipse/handlers/HandleConstructor.java @@ -33,6 +33,7 @@ import java.util.List; import lombok.AccessLevel; import lombok.AllArgsConstructor; +import lombok.Builder; import lombok.ConfigurationKeys; import lombok.NoArgsConstructor; import lombok.RequiredArgsConstructor; @@ -40,7 +41,6 @@ import lombok.core.AST.Kind; import lombok.core.AnnotationValues; import lombok.eclipse.EclipseAnnotationHandler; import lombok.eclipse.EclipseNode; -import lombok.experimental.Builder; import org.eclipse.jdt.internal.compiler.ast.ASTNode; import org.eclipse.jdt.internal.compiler.ast.AllocationExpression; diff --git a/src/core/lombok/experimental/Builder.java b/src/core/lombok/experimental/Builder.java index 1300e7d3..7d89109f 100644 --- a/src/core/lombok/experimental/Builder.java +++ b/src/core/lombok/experimental/Builder.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013 The Project Lombok Authors. + * 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 @@ -103,9 +103,12 @@ import java.lang.annotation.Target; * } * } * </pre> + * + * @deprecated {@link lombok.Builder} has been promoted to the main package, so use that one instead. */ @Target({TYPE, METHOD, CONSTRUCTOR}) @Retention(SOURCE) +@Deprecated public @interface Builder { /** Name of the static method that creates a new builder instance. Default: {@code builder}. */ String builderMethodName() default "builder"; diff --git a/src/core/lombok/javac/handlers/HandleBuilder.java b/src/core/lombok/javac/handlers/HandleBuilder.java index 1885b8b4..08acc268 100644 --- a/src/core/lombok/javac/handlers/HandleBuilder.java +++ b/src/core/lombok/javac/handlers/HandleBuilder.java @@ -46,11 +46,11 @@ import com.sun.tools.javac.util.ListBuffer; import com.sun.tools.javac.util.Name; import lombok.AccessLevel; +import lombok.Builder; import lombok.ConfigurationKeys; import lombok.core.AST.Kind; import lombok.core.AnnotationValues; import lombok.core.HandlerPriority; -import lombok.experimental.Builder; import lombok.experimental.NonFinal; import lombok.javac.JavacAnnotationHandler; import lombok.javac.JavacNode; @@ -64,10 +64,20 @@ import static lombok.javac.JavacTreeMaker.TypeTag.*; @ProviderFor(JavacAnnotationHandler.class) @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> { + private static final boolean toBoolean(Object expr, boolean defaultValue) { + if (expr == null) return defaultValue; + return ((Boolean) expr).booleanValue(); + } + @Override public void handle(AnnotationValues<Builder> annotation, JCAnnotation ast, JavacNode annotationNode) { handleExperimentalFlagUsage(annotationNode, ConfigurationKeys.BUILDER_FLAG_USAGE, "@Builder"); Builder builderInstance = annotation.getInstance(); + + // These exist just to support the 'old' lombok.experimental.Builder, which had these properties. lombok.Builder no longer has them. + boolean fluent = toBoolean(annotation.getActualExpression("fluent"), true); + boolean chain = toBoolean(annotation.getActualExpression("chain"), true); + String builderMethodName = builderInstance.builderMethodName(); String buildMethodName = builderInstance.buildMethodName(); String builderClassName = builderInstance.builderClassName(); @@ -194,7 +204,7 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> { java.util.List<JavacNode> fieldNodes = addFieldsToBuilder(builderType, namesOfParameters, typesOfParameters, ast); java.util.List<JCMethodDecl> newMethods = new ArrayList<JCMethodDecl>(); for (JavacNode fieldNode : fieldNodes) { - JCMethodDecl newMethod = makeSetterMethodForBuilder(builderType, fieldNode, annotationNode, builderInstance.fluent(), builderInstance.chain()); + JCMethodDecl newMethod = makeSetterMethodForBuilder(builderType, fieldNode, annotationNode, fluent, chain); if (newMethod != null) newMethods.add(newMethod); } diff --git a/src/core/lombok/javac/handlers/HandleConstructor.java b/src/core/lombok/javac/handlers/HandleConstructor.java index 6043d1cb..c5b309c2 100644 --- a/src/core/lombok/javac/handlers/HandleConstructor.java +++ b/src/core/lombok/javac/handlers/HandleConstructor.java @@ -25,13 +25,13 @@ import static lombok.core.handlers.HandlerUtil.*; import static lombok.javac.handlers.JavacHandlerUtil.*; import lombok.AccessLevel; import lombok.AllArgsConstructor; +import lombok.Builder; import lombok.ConfigurationKeys; import lombok.NoArgsConstructor; import lombok.RequiredArgsConstructor; import lombok.core.AnnotationValues; import lombok.core.AST.Kind; import lombok.delombok.LombokOptionsFactory; -import lombok.experimental.Builder; import lombok.javac.JavacAnnotationHandler; import lombok.javac.JavacNode; import lombok.javac.JavacTreeMaker; diff --git a/src/utils/lombok/core/LombokImmutableList.java b/src/utils/lombok/core/LombokImmutableList.java index e0e1136c..4603f2ad 100644 --- a/src/utils/lombok/core/LombokImmutableList.java +++ b/src/utils/lombok/core/LombokImmutableList.java @@ -80,6 +80,12 @@ public final class LombokImmutableList<T> implements Iterable<T> { return copyOf(list); } + public static <T> LombokImmutableList<T> copyOf(T[] array) { + Object[] content = new Object[array.length]; + System.arraycopy(array, 0, content, 0, array.length); + return new LombokImmutableList<T>(content); + } + private LombokImmutableList(Object[] content) { this.content = content; } |