aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/core/lombok/AllArgsConstructor.java19
-rw-r--r--src/core/lombok/Builder.java33
-rw-r--r--src/core/lombok/Cleanup.java6
-rw-r--r--src/core/lombok/ConfigurationKeys.java13
-rw-r--r--src/core/lombok/Data.java6
-rw-r--r--src/core/lombok/Delegate.java6
-rw-r--r--src/core/lombok/EqualsAndHashCode.java30
-rw-r--r--src/core/lombok/Getter.java22
-rw-r--r--src/core/lombok/Lombok.java24
-rw-r--r--src/core/lombok/NoArgsConstructor.java20
-rw-r--r--src/core/lombok/RequiredArgsConstructor.java18
-rw-r--r--src/core/lombok/Setter.java26
-rw-r--r--src/core/lombok/Singular.java4
-rw-r--r--src/core/lombok/SneakyThrows.java9
-rw-r--r--src/core/lombok/Synchronized.java6
-rw-r--r--src/core/lombok/ToString.java14
-rw-r--r--src/core/lombok/Value.java6
-rw-r--r--src/core/lombok/core/PublicApiCreatorApp.java2
-rw-r--r--src/core/lombok/core/Version.java14
-rw-r--r--src/core/lombok/core/handlers/singulars.txt6
-rw-r--r--src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java19
-rw-r--r--src/core/lombok/eclipse/handlers/EclipseSingularsRecipes.java8
-rw-r--r--src/core/lombok/eclipse/handlers/HandleBuilder.java125
-rw-r--r--src/core/lombok/eclipse/handlers/HandleBuilderDefault.java25
-rw-r--r--src/core/lombok/eclipse/handlers/HandleConstructor.java11
-rw-r--r--src/core/lombok/eclipse/handlers/HandleEqualsAndHashCode.java5
-rw-r--r--src/core/lombok/eclipse/handlers/HandleSetter.java13
-rw-r--r--src/core/lombok/eclipse/handlers/HandleToString.java6
-rw-r--r--src/core/lombok/eclipse/handlers/singulars/EclipseGuavaSingularizer.java21
-rw-r--r--src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilListSetSingularizer.java22
-rw-r--r--src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilMapSingularizer.java23
-rw-r--r--src/core/lombok/experimental/Accessors.java18
-rw-r--r--src/core/lombok/experimental/Builder.java21
-rw-r--r--src/core/lombok/experimental/Delegate.java8
-rw-r--r--src/core/lombok/experimental/ExtensionMethod.java10
-rw-r--r--src/core/lombok/experimental/FieldDefaults.java4
-rw-r--r--src/core/lombok/experimental/Value.java6
-rw-r--r--src/core/lombok/experimental/Wither.java26
-rw-r--r--src/core/lombok/experimental/package-info.java4
-rw-r--r--src/core/lombok/extern/apachecommons/CommonsLog.java14
-rw-r--r--src/core/lombok/extern/java/Log.java14
-rw-r--r--src/core/lombok/extern/jbosslog/JBossLog.java15
-rw-r--r--src/core/lombok/extern/log4j/Log4j.java14
-rw-r--r--src/core/lombok/extern/log4j/Log4j2.java14
-rw-r--r--src/core/lombok/extern/slf4j/Slf4j.java14
-rw-r--r--src/core/lombok/extern/slf4j/XSlf4j.java14
-rw-r--r--src/core/lombok/javac/CompilerMessageSuppressor.java206
-rw-r--r--src/core/lombok/javac/JavacAST.java145
-rw-r--r--src/core/lombok/javac/apt/LombokFileObjects.java42
-rw-r--r--src/core/lombok/javac/handlers/HandleBuilder.java102
-rw-r--r--src/core/lombok/javac/handlers/HandleBuilderDefault.java29
-rw-r--r--src/core/lombok/javac/handlers/HandleConstructor.java8
-rw-r--r--src/core/lombok/javac/handlers/HandleEqualsAndHashCode.java5
-rw-r--r--src/core/lombok/javac/handlers/HandleSetter.java11
-rw-r--r--src/core/lombok/javac/handlers/HandleToString.java6
-rw-r--r--src/core/lombok/javac/handlers/JavacHandlerUtil.java22
-rw-r--r--src/core/lombok/javac/handlers/JavacSingularsRecipes.java12
-rw-r--r--src/core/lombok/javac/handlers/singulars/JavacGuavaSingularizer.java23
-rw-r--r--src/core/lombok/javac/handlers/singulars/JavacJavaUtilListSetSingularizer.java26
-rw-r--r--src/core/lombok/javac/handlers/singulars/JavacJavaUtilMapSingularizer.java26
-rw-r--r--src/core/lombok/javac/handlers/singulars/JavacJavaUtilSingularizer.java3
-rw-r--r--src/core/lombok/package-info.java4
-rw-r--r--src/core/lombok/val.java4
-rw-r--r--src/installer/lombok/installer/InstallerGUI.java5
-rw-r--r--src/utils/lombok/javac/TreeMirrorMaker.java7
-rw-r--r--src/website/log4j.properties6
-rw-r--r--src/website/lombok/website/CompileChangelog.java114
-rw-r--r--src/website/lombok/website/WebsiteMaker.java403
68 files changed, 1541 insertions, 426 deletions
diff --git a/src/core/lombok/AllArgsConstructor.java b/src/core/lombok/AllArgsConstructor.java
index 75f87211..c059c65d 100644
--- a/src/core/lombok/AllArgsConstructor.java
+++ b/src/core/lombok/AllArgsConstructor.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010-2013 The Project Lombok Authors.
+ * Copyright (C) 2010-2017 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,7 +30,7 @@ import java.lang.annotation.Target;
* Generates an all-args constructor.
* An all-args constructor requires one argument for every field in the class.
* <p>
- * Complete documentation is found at <a href="https://projectlombok.org/features/Constructor.html">the project lombok features page for &#64;Constructor</a>.
+ * Complete documentation is found at <a href="https://projectlombok.org/features/Constructor">the project lombok features page for &#64;Constructor</a>.
* <p>
* Even though it is not listed, this annotation also has the {@code onConstructor} parameter. See the full documentation for more details.
*
@@ -45,26 +45,33 @@ public @interface AllArgsConstructor {
* is generated with the same argument list that wraps the real constructor.
*
* Such a static 'constructor' is primarily useful as it infers type arguments.
+ *
+ * @return Name of static 'constructor' method to generate (blank = generate a normal constructor).
*/
String staticName() default "";
/**
* Any annotations listed here are put on the generated constructor.
- * The syntax for this feature depends on JDK version (nothing we can do about that; it's to work around javac bugs).<br />
- * up to JDK7:<br />
- * {@code @AllArgsConstructor(onConstructor=@__({@AnnotationsGoHere}))}<br />
- * from JDK8:<br />
+ * The syntax for this feature depends on JDK version (nothing we can do about that; it's to work around javac bugs).<br>
+ * up to JDK7:<br>
+ * {@code @AllArgsConstructor(onConstructor=@__({@AnnotationsGoHere}))}<br>
+ * from JDK8:<br>
* {@code @AllArgsConstructor(onConstructor_={@AnnotationsGohere})} // note the underscore after {@code onConstructor}.
+ *
+ * @return List of annotations to apply to the generated constructor.
*/
AnyAnnotation[] onConstructor() default {};
/**
* Sets the access level of the constructor. By default, generated constructors are {@code public}.
+ *
+ * @return The constructor will be generated with this access modifier.
*/
AccessLevel access() default lombok.AccessLevel.PUBLIC;
/**
* Placeholder annotation to enable the placement of annotations on the generated code.
+ *
* @deprecated Don't use this annotation, ever - Read the documentation.
*/
@Deprecated
diff --git a/src/core/lombok/Builder.java b/src/core/lombok/Builder.java
index 7a965486..af3c3c06 100644
--- a/src/core/lombok/Builder.java
+++ b/src/core/lombok/Builder.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013-2014 The Project Lombok Authors.
+ * Copyright (C) 2013-2017 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
@@ -48,8 +48,8 @@ import java.lang.annotation.Target;
* as the relevant class, unless a 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="https://projectlombok.org/features/experimental/Builder.html">the project lombok features page for &#64;Builder</a>.
- * <p>
+ * Complete documentation is found at <a href="https://projectlombok.org/features/experimental/Builder">the project lombok features page for &#64;Builder</a>.
+ * <br>
* <p>
* Before:
*
@@ -107,10 +107,17 @@ import java.lang.annotation.Target;
@Target({TYPE, METHOD, CONSTRUCTOR})
@Retention(SOURCE)
public @interface Builder {
- /** Name of the method that creates a new builder instance. Default: {@code builder}. */
+ /**
+ * The field annotated with {@code @Default} must have an initializing expression; that expression is taken as the default to be used if not explicitly set during building.
+ */
+ @Target(FIELD)
+ @Retention(SOURCE)
+ public @interface Default {}
+
+ /** @return Name of the method that creates a new builder instance. Default: {@code builder}. */
String builderMethodName() default "builder";
- /** Name of the method in the builder class that creates an instance of your {@code @Builder}-annotated class. */
+ /** @return Name of the method in the builder class that creates an instance of your {@code @Builder}-annotated class. */
String buildMethodName() default "build";
/**
@@ -119,6 +126,8 @@ public @interface Builder {
* Default for {@code @Builder} on types and constructors: {@code (TypeName)Builder}.
* <p>
* Default for {@code @Builder} on methods: {@code (ReturnTypeName)Builder}.
+ *
+ * @return Name of the builder class that will be generated (or if it already exists, will be filled with builder elements).
*/
String builderClassName() default "";
@@ -126,6 +135,8 @@ public @interface Builder {
* If true, generate an instance method to obtain a builder that is initialized with the values of this instance.
* Legal only if {@code @Builder} is used on a constructor, on the type itself, or on a static method that returns
* an instance of the declaring type.
+ *
+ * @return Whether to generate a {@code toBuilder()} method.
*/
boolean toBuilder() default false;
@@ -142,13 +153,19 @@ public @interface Builder {
@Target({FIELD, PARAMETER})
@Retention(SOURCE)
public @interface ObtainVia {
- /** Tells lombok to obtain a value with the expression {@code this.value}. */
+ /**
+ * @return Tells lombok to obtain a value with the expression {@code this.value}.
+ */
String field() default "";
- /** Tells lombok to obtain a value with the expression {@code this.method()}. */
+ /**
+ * @return Tells lombok to obtain a value with the expression {@code this.method()}.
+ */
String method() default "";
- /** Tells lombok to obtain a value with the expression {@code SelfType.method(this)}; requires {@code method} to be set. */
+ /**
+ * @return Tells lombok to obtain a value with the expression {@code SelfType.method(this)}; requires {@code method} to be set.
+ */
boolean isStatic() default false;
}
}
diff --git a/src/core/lombok/Cleanup.java b/src/core/lombok/Cleanup.java
index c95c03c5..528855cd 100644
--- a/src/core/lombok/Cleanup.java
+++ b/src/core/lombok/Cleanup.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009-2013 The Project Lombok Authors.
+ * Copyright (C) 2009-2017 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
@@ -31,7 +31,7 @@ import java.lang.annotation.Target;
* of what happens. Implemented by wrapping all statements following the local variable declaration to the
* end of your scope into a try block that, as a finally action, closes the resource.
* <p>
- * Complete documentation is found at <a href="https://projectlombok.org/features/Cleanup.html">the project lombok features page for &#64;Cleanup</a>.
+ * Complete documentation is found at <a href="https://projectlombok.org/features/Cleanup">the project lombok features page for &#64;Cleanup</a>.
* <p>
* Example:
* <pre>
@@ -72,6 +72,6 @@ import java.lang.annotation.Target;
@Target(ElementType.LOCAL_VARIABLE)
@Retention(RetentionPolicy.SOURCE)
public @interface Cleanup {
- /** The name of the method that cleans up the resource. By default, 'close'. The method must not have any parameters. */
+ /** @return The name of the method that cleans up the resource. By default, 'close'. The method must not have any parameters. */
String value() default "close";
}
diff --git a/src/core/lombok/ConfigurationKeys.java b/src/core/lombok/ConfigurationKeys.java
index f0e070e2..90621027 100644
--- a/src/core/lombok/ConfigurationKeys.java
+++ b/src/core/lombok/ConfigurationKeys.java
@@ -261,7 +261,7 @@ public class ConfigurationKeys {
// ----- NonNull -----
/**
- * lombok configuration: {@code lombok.nonNull.exceptionType} = &lt;String: <em>a java exception type; either [{@code IllegalArgumentException} or: {@code NullPointerException}].
+ * lombok configuration: {@code lombok.nonNull.exceptionType} = &lt;String: <em>a java exception type</em>; either [{@code IllegalArgumentException} or: {@code NullPointerException}].
*
* Sets the exception to throw if {@code @NonNull} is applied to a method parameter, and a caller passes in {@code null}.
*/
@@ -460,6 +460,17 @@ public class ConfigurationKeys {
*/
public static final ConfigurationKey<FlagUsageType> HELPER_FLAG_USAGE = new ConfigurationKey<FlagUsageType>("lombok.helper.flagUsage", "Emit a warning or error if @Helper is used.") {};
+ // ----- onX -----
+
+ /**
+ * lombok configuration: {@code lombok.onX.flagUsage} = {@code WARNING} | {@code ERROR}.
+ *
+ * If set, <em>any</em> usage of {@code onX} results in a warning / error.
+ * <br>
+ * Specifically, this flags usage of {@code @Getter(onMethod=...)}, {@code @Setter(onParam=...)}, {@code @Setter(onMethod=...)}, {@code @XArgsConstructor(onConstructor=...)}.
+ */
+ public static final ConfigurationKey<FlagUsageType> ON_X_FLAG_USAGE = new ConfigurationKey<FlagUsageType>("lombok.onX.flagUsage", "Emit a warning or error if onX is used.") {};
+
// ----- UtilityClass -----
/**
diff --git a/src/core/lombok/Data.java b/src/core/lombok/Data.java
index 4c6c2e5d..ffa968c1 100644
--- a/src/core/lombok/Data.java
+++ b/src/core/lombok/Data.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009-2013 The Project Lombok Authors.
+ * Copyright (C) 2009-2017 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
@@ -32,7 +32,7 @@ import java.lang.annotation.Target;
* <p>
* Equivalent to {@code @Getter @Setter @RequiredArgsConstructor @ToString @EqualsAndHashCode}.
* <p>
- * Complete documentation is found at <a href="https://projectlombok.org/features/Data.html">the project lombok features page for &#64;Data</a>.
+ * Complete documentation is found at <a href="https://projectlombok.org/features/Data">the project lombok features page for &#64;Data</a>.
*
* @see Getter
* @see Setter
@@ -54,6 +54,8 @@ public @interface Data {
* </pre>
*
* Default: No static constructor, instead the normal constructor is public.
+ *
+ * @return Name of static 'constructor' method to generate (blank = generate a normal constructor).
*/
String staticConstructor() default "";
}
diff --git a/src/core/lombok/Delegate.java b/src/core/lombok/Delegate.java
index d5b4b48c..0c5a4c2c 100644
--- a/src/core/lombok/Delegate.java
+++ b/src/core/lombok/Delegate.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010-2014 The Project Lombok Authors.
+ * Copyright (C) 2010-2017 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
@@ -40,6 +40,8 @@ public @interface Delegate {
* type listed here is used only to determine which delegate methods to generate.
*
* NB: All methods in {@code Object}, as well as {@code canEqual(Object other)} will never be delegated.
+ *
+ * @return For each method (not already in {@code java.lang.Object}) in these types, generate a delegate method.
*/
Class<?>[] types() default {};
@@ -47,6 +49,8 @@ public @interface Delegate {
* Each method in any of the types listed here (include supertypes) will <em>not</em> be delegated.
*
* NB: All methods in {@code Object}, as well as {@code canEqual(Object other)} will never be delegated.
+ *
+ * @return For each method (not already in {@code java.lang.Object}) in these types, skip generating a delegate method (overrides {@code types()}).
*/
Class<?>[] excludes() default {};
}
diff --git a/src/core/lombok/EqualsAndHashCode.java b/src/core/lombok/EqualsAndHashCode.java
index 34f4ffc6..2f88ac50 100644
--- a/src/core/lombok/EqualsAndHashCode.java
+++ b/src/core/lombok/EqualsAndHashCode.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009-2014 The Project Lombok Authors.
+ * Copyright (C) 2009-2017 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
@@ -29,15 +29,16 @@ import java.lang.annotation.Target;
/**
* Generates implementations for the {@code equals} and {@code hashCode} methods inherited by all objects, based on relevant fields.
* <p>
- * Complete documentation is found at <a href="https://projectlombok.org/features/EqualsAndHashCode.html">the project lombok features page for &#64;EqualsAndHashCode</a>.
+ * Complete documentation is found at <a href="https://projectlombok.org/features/EqualsAndHashCode">the project lombok features page for &#64;EqualsAndHashCode</a>.
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.SOURCE)
public @interface EqualsAndHashCode {
/**
- * Any fields listed here will not be taken into account in the generated
- * {@code equals} and {@code hashCode} implementations.
+ * Any fields listed here will not be taken into account in the generated {@code equals} and {@code hashCode} implementations.
* Mutually exclusive with {@link #of()}.
+ *
+ * @return A list of fields to exclude.
*/
String[] exclude() default {};
@@ -46,30 +47,37 @@ public @interface EqualsAndHashCode {
* Normally, all non-static, non-transient fields are used for identity.
* <p>
* Mutually exclusive with {@link #exclude()}.
+ *
+ * @return A list of fields to use (<em>default</em>: all of them).
*/
String[] of() default {};
/**
- * Call on the superclass's implementations of {@code equals} and {@code hashCode} before calculating
- * for the fields in this class.
+ * Call on the superclass's implementations of {@code equals} and {@code hashCode} before calculating for the fields in this class.
* <strong>default: false</strong>
+ *
+ * @return Whether to call the superclass's {@code equals} implementation as part of the generated equals algorithm.
*/
boolean callSuper() default false;
/**
* Normally, if getters are available, those are called. To suppress this and let the generated code use the fields directly, set this to {@code true}.
* <strong>default: false</strong>
+ *
+ * @return If {@code true}, always use direct field access instead of calling the getter method.
*/
boolean doNotUseGetters() default false;
/**
* Any annotations listed here are put on the generated parameter of {@code equals} and {@code canEqual}.
- * This is useful to add for example a {@code Nullable} annotation.<br />
- * The syntax for this feature depends on JDK version (nothing we can do about that; it's to work around javac bugs).<br />
- * up to JDK7:<br />
- * {@code @EqualsAndHashCode(onParam=@__({@AnnotationsGoHere}))}<br />
- * from JDK8:<br />
+ * This is useful to add for example a {@code Nullable} annotation.<br>
+ * The syntax for this feature depends on JDK version (nothing we can do about that; it's to work around javac bugs).<br>
+ * up to JDK7:<br>
+ * {@code @EqualsAndHashCode(onParam=@__({@AnnotationsGoHere}))}<br>
+ * from JDK8:<br>
* {@code @EqualsAndHashCode(onParam_={@AnnotationsGohere})} // note the underscore after {@code onParam}.
+ *
+ * @return List of annotations to apply to the generated parameter in the {@code equals()} method.
*/
AnyAnnotation[] onParam() default {};
diff --git a/src/core/lombok/Getter.java b/src/core/lombok/Getter.java
index 5a4056fa..5a23fe30 100644
--- a/src/core/lombok/Getter.java
+++ b/src/core/lombok/Getter.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009-2013 The Project Lombok Authors.
+ * Copyright (C) 2009-2017 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
@@ -29,7 +29,7 @@ import java.lang.annotation.Target;
/**
* Put on any field to make lombok build a standard getter.
* <p>
- * Complete documentation is found at <a href="https://projectlombok.org/features/GetterSetter.html">the project lombok features page for &#64;Getter and &#64;Setter</a>.
+ * Complete documentation is found at <a href="https://projectlombok.org/features/GetterSetter">the project lombok features page for &#64;Getter and &#64;Setter</a>.
* <p>
* Even though it is not listed, this annotation also has the {@code onMethod} parameter. See the full documentation for more details.
* <p>
@@ -54,25 +54,29 @@ import java.lang.annotation.Target;
public @interface Getter {
/**
* If you want your getter to be non-public, you can specify an alternate access level here.
+ *
+ * @return The getter method will be generated with this access modifier.
*/
lombok.AccessLevel value() default lombok.AccessLevel.PUBLIC;
/**
* Any annotations listed here are put on the generated method.
- * The syntax for this feature depends on JDK version (nothing we can do about that; it's to work around javac bugs).<br />
- * up to JDK7:<br />
- * {@code @Getter(onMethod=@__({@AnnotationsGoHere}))}<br />
- * from JDK8:<br />
+ * The syntax for this feature depends on JDK version (nothing we can do about that; it's to work around javac bugs).<br>
+ * up to JDK7:<br>
+ * {@code @Getter(onMethod=@__({@AnnotationsGoHere}))}<br>
+ * from JDK8:<br>
* {@code @Getter(onMethod_={@AnnotationsGohere})} // note the underscore after {@code onMethod}.
+ *
+ * @return List of annotations to apply to the generated getter method.
*/
AnyAnnotation[] onMethod() default {};
boolean lazy() default false;
/**
- * Placeholder annotation to enable the placement of annotations on the generated code.
- * @deprecated Don't use this annotation, ever - Read the documentation.
- */
+ * Placeholder annotation to enable the placement of annotations on the generated code.
+ * @deprecated Don't use this annotation, ever - Read the documentation.
+ */
@Deprecated
@Retention(RetentionPolicy.SOURCE)
@Target({})
diff --git a/src/core/lombok/Lombok.java b/src/core/lombok/Lombok.java
index 164c47a8..310b57e3 100644
--- a/src/core/lombok/Lombok.java
+++ b/src/core/lombok/Lombok.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009 The Project Lombok Authors.
+ * Copyright (C) 2009-2017 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,7 +30,6 @@ public class Lombok {
* The exception is still thrown - javac will just stop whining about it.
* <p>
* Example usage:
- * <p>
* <pre>public void run() {
* throw sneakyThrow(new IOException("You don't need to catch me!"));
* }</pre>
@@ -59,14 +58,13 @@ public class Lombok {
}
/**
- * Returns the parameter directly. <br />
+ * Returns the parameter directly.
*
- * This method can be used to prevent a static analyzer to determine
- * the nullness of the passed parameter.
+ * This method can be used to prevent a static analyzer to determine the nullness of the passed parameter.
*
- * @param <T> the type of the parameter
- * @param value the value to return
- * @return value
+ * @param <T> the type of the parameter.
+ * @param value the value to return.
+ * @return value (this method just returns the parameter).
*/
public static <T> T preventNullAnalysis(T value) {
return value;
@@ -74,10 +72,12 @@ public class Lombok {
/**
* Ensures that the {@code value} is not {@code null}.
- * @param value the value to test for null
- * @param message the message of the {@link NullPointerException}
- * @return the value if it is not null
- * @throws NullPointerException with the {@code message} if the value is null
+ *
+ * @param <T> Type of the parameter.
+ * @param value the value to test for null.
+ * @param message the message of the {@link NullPointerException}.
+ * @return the value if it is not null.
+ * @throws NullPointerException with the {@code message} if the value is null.
*/
public static <T> T checkNotNull(T value, String message) {
if (value == null) throw new NullPointerException(message);
diff --git a/src/core/lombok/NoArgsConstructor.java b/src/core/lombok/NoArgsConstructor.java
index 5f2268a8..672cd1c2 100644
--- a/src/core/lombok/NoArgsConstructor.java
+++ b/src/core/lombok/NoArgsConstructor.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010-2015 The Project Lombok Authors.
+ * Copyright (C) 2010-2017 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,7 +30,7 @@ import java.lang.annotation.Target;
* Generates a no-args constructor.
* Will generate an error message if such a constructor cannot be written due to the existence of final fields.
* <p>
- * Complete documentation is found at <a href="https://projectlombok.org/features/Constructor.html">the project lombok features page for &#64;Constructor</a>.
+ * Complete documentation is found at <a href="https://projectlombok.org/features/Constructor">the project lombok features page for &#64;Constructor</a>.
* <p>
* Even though it is not listed, this annotation also has the {@code onConstructor} parameter. See the full documentation for more details.
* <p>
@@ -47,27 +47,35 @@ public @interface NoArgsConstructor {
* is generated with the same argument list that wraps the real constructor.
*
* Such a static 'constructor' is primarily useful as it infers type arguments.
+ *
+ * @return Name of static 'constructor' method to generate (blank = generate a normal constructor).
*/
String staticName() default "";
/**
* Any annotations listed here are put on the generated constructor.
- * The syntax for this feature depends on JDK version (nothing we can do about that; it's to work around javac bugs).<br />
- * up to JDK7:<br />
- * {@code @NoArgsConstructor(onConstructor=@__({@AnnotationsGoHere}))}<br />
- * from JDK8:<br />
+ * The syntax for this feature depends on JDK version (nothing we can do about that; it's to work around javac bugs).<br>
+ * up to JDK7:<br>
+ * {@code @NoArgsConstructor(onConstructor=@__({@AnnotationsGoHere}))}<br>
+ * from JDK8:<br>
* {@code @NoArgsConstructor(onConstructor_={@AnnotationsGohere})} // note the underscore after {@code onConstructor}.
+ *
+ * @return List of annotations to apply to the generated constructor.
*/
AnyAnnotation[] onConstructor() default {};
/**
* Sets the access level of the constructor. By default, generated constructors are {@code public}.
+ *
+ * @return The constructor will be generated with this access modifier.
*/
AccessLevel access() default lombok.AccessLevel.PUBLIC;
/**
* If {@code true}, initializes all final fields to 0 / null / false.
* Otherwise, a compile time error occurs.
+ *
+ * @return Return {@code} true to force generation of a no-args constructor, picking defaults if necessary to assign required fields.
*/
boolean force() default false;
diff --git a/src/core/lombok/RequiredArgsConstructor.java b/src/core/lombok/RequiredArgsConstructor.java
index 2f4d0aaf..f21bd647 100644
--- a/src/core/lombok/RequiredArgsConstructor.java
+++ b/src/core/lombok/RequiredArgsConstructor.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010-2013 The Project Lombok Authors.
+ * Copyright (C) 2010-2017 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,7 +30,7 @@ import java.lang.annotation.Target;
* Generates a constructor with required arguments.
* Required arguments are final fields and fields with constraints such as {@code @NonNull}.
* <p>
- * Complete documentation is found at <a href="https://projectlombok.org/features/Constructor.html">the project lombok features page for &#64;Constructor</a>.
+ * Complete documentation is found at <a href="https://projectlombok.org/features/Constructor">the project lombok features page for &#64;Constructor</a>.
* <p>
* Even though it is not listed, this annotation also has the {@code onConstructor} parameter. See the full documentation for more details.
*
@@ -45,21 +45,27 @@ public @interface RequiredArgsConstructor {
* is generated with the same argument list that wraps the real constructor.
*
* Such a static 'constructor' is primarily useful as it infers type arguments.
+ *
+ * @return Name of static 'constructor' method to generate (blank = generate a normal constructor).
*/
String staticName() default "";
/**
* Any annotations listed here are put on the generated constructor.
- * The syntax for this feature depends on JDK version (nothing we can do about that; it's to work around javac bugs).<br />
- * up to JDK7:<br />
- * {@code @RequiredArgsConstructor(onConstructor=@__({@AnnotationsGoHere}))}<br />
- * from JDK8:<br />
+ * The syntax for this feature depends on JDK version (nothing we can do about that; it's to work around javac bugs).<br>
+ * up to JDK7:<br>
+ * {@code @RequiredArgsConstructor(onConstructor=@__({@AnnotationsGoHere}))}<br>
+ * from JDK8:<br>
* {@code @RequiredArgsConstructor(onConstructor_={@AnnotationsGohere})} // note the underscore after {@code onConstructor}.
+ *
+ * @return List of annotations to apply to the generated constructor.
*/
AnyAnnotation[] onConstructor() default {};
/**
* Sets the access level of the constructor. By default, generated constructors are {@code public}.
+ *
+ * @return The constructor will be generated with this access modifier.
*/
AccessLevel access() default lombok.AccessLevel.PUBLIC;
diff --git a/src/core/lombok/Setter.java b/src/core/lombok/Setter.java
index f2ebe5b3..1b70bac9 100644
--- a/src/core/lombok/Setter.java
+++ b/src/core/lombok/Setter.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009-2013 The Project Lombok Authors.
+ * Copyright (C) 2009-2017 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
@@ -29,7 +29,7 @@ import java.lang.annotation.Target;
/**
* Put on any field to make lombok build a standard setter.
* <p>
- * Complete documentation is found at <a href="https://projectlombok.org/features/GetterSetter.html">the project lombok features page for &#64;Getter and &#64;Setter</a>.
+ * Complete documentation is found at <a href="https://projectlombok.org/features/GetterSetter">the project lombok features page for &#64;Getter and &#64;Setter</a>.
* <p>
* Even though it is not listed, this annotation also has the {@code onParam} and {@code onMethod} parameter. See the full documentation for more details.
* <p>
@@ -55,26 +55,32 @@ import java.lang.annotation.Target;
public @interface Setter {
/**
* If you want your setter to be non-public, you can specify an alternate access level here.
+ *
+ * @return The setter method will be generated with this access modifier.
*/
lombok.AccessLevel value() default lombok.AccessLevel.PUBLIC;
/**
* Any annotations listed here are put on the generated method.
- * The syntax for this feature depends on JDK version (nothing we can do about that; it's to work around javac bugs).<br />
- * up to JDK7:<br />
- * {@code @Setter(onMethod=@__({@AnnotationsGoHere}))}<br />
- * from JDK8:<br />
+ * The syntax for this feature depends on JDK version (nothing we can do about that; it's to work around javac bugs).<br>
+ * up to JDK7:<br>
+ * {@code @Setter(onMethod=@__({@AnnotationsGoHere}))}<br>
+ * from JDK8:<br>
* {@code @Setter(onMethod_={@AnnotationsGohere})} // note the underscore after {@code onMethod}.
+ *
+ * @return List of annotations to apply to the generated setter method.
*/
AnyAnnotation[] onMethod() default {};
/**
* Any annotations listed here are put on the generated method's parameter.
- * The syntax for this feature depends on JDK version (nothing we can do about that; it's to work around javac bugs).<br />
- * up to JDK7:<br />
- * {@code @Setter(onParam=@__({@AnnotationsGoHere}))}<br />
- * from JDK8:<br />
+ * The syntax for this feature depends on JDK version (nothing we can do about that; it's to work around javac bugs).<br>
+ * up to JDK7:<br>
+ * {@code @Setter(onParam=@__({@AnnotationsGoHere}))}<br>
+ * from JDK8:<br>
* {@code @Setter(onParam_={@AnnotationsGohere})} // note the underscore after {@code onParam}.
+ *
+ * @return List of annotations to apply to the generated parameter in the setter method.
*/
AnyAnnotation[] onParam() default {};
diff --git a/src/core/lombok/Singular.java b/src/core/lombok/Singular.java
index 15dec4a5..67edab96 100644
--- a/src/core/lombok/Singular.java
+++ b/src/core/lombok/Singular.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2015 The Project Lombok Authors.
+ * Copyright (C) 2015-2017 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
@@ -29,10 +29,10 @@ import java.lang.annotation.Target;
/**
* The singular annotation is used together with {@code @Builder} to create single element 'add' methods in the builder for collections.
- * <p>
*/
@Target({FIELD, PARAMETER})
@Retention(SOURCE)
public @interface Singular {
+ /** @return The singular name of this field. If it's a normal english plural, lombok will figure it out automatically. Otherwise, this parameter is mandatory. */
String value() default "";
}
diff --git a/src/core/lombok/SneakyThrows.java b/src/core/lombok/SneakyThrows.java
index 489e13e4..0506d615 100644
--- a/src/core/lombok/SneakyThrows.java
+++ b/src/core/lombok/SneakyThrows.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009-2013 The Project Lombok Authors.
+ * Copyright (C) 2009-2017 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
@@ -34,7 +34,7 @@ import java.lang.annotation.Target;
* checked exception types. The JVM does not check for the consistency of the checked exception system; javac does,
* and this annotation lets you opt out of its mechanism.
* <p>
- * Complete documentation is found at <a href="https://projectlombok.org/features/SneakyThrows.html">the project lombok features page for &#64;SneakyThrows</a>.
+ * Complete documentation is found at <a href="https://projectlombok.org/features/SneakyThrows">the project lombok features page for &#64;SneakyThrows</a>.
* <p>
* Example:
* <pre>
@@ -59,8 +59,9 @@ import java.lang.annotation.Target;
@Target({ElementType.METHOD, ElementType.CONSTRUCTOR})
@Retention(RetentionPolicy.SOURCE)
public @interface SneakyThrows {
- /** The exception type(s) you want to sneakily throw onward. */
+ /** @return The exception type(s) you want to sneakily throw onward. */
Class<? extends Throwable>[] value() default java.lang.Throwable.class;
- //The package is mentioned in java.lang due to a bug in javac (presence of an annotation processor throws off the type resolver for some reason).
+ //The fully qualified name is used for java.lang.Throwable in the parameter only. This works around a bug in javac:
+ // presence of an annotation processor throws off the type resolver for some reason.
}
diff --git a/src/core/lombok/Synchronized.java b/src/core/lombok/Synchronized.java
index 9a39c212..5dff0fb2 100644
--- a/src/core/lombok/Synchronized.java
+++ b/src/core/lombok/Synchronized.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009-2013 The Project Lombok Authors.
+ * Copyright (C) 2009-2017 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
@@ -35,7 +35,7 @@ import java.lang.annotation.Target;
* {@code $LOCK} is used. These will be generated if needed and if they aren't already present. The contents
* of the fields will be serializable.
* <p>
- * Complete documentation is found at <a href="https://projectlombok.org/features/Synchronized.html">the project lombok features page for &#64;Synchronized</a>.
+ * Complete documentation is found at <a href="https://projectlombok.org/features/Synchronized">the project lombok features page for &#64;Synchronized</a>.
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
@@ -43,6 +43,8 @@ public @interface Synchronized {
/**
* Optional: specify the name of a different field to lock on. It is a compile time error if this field
* doesn't already exist (the fields are automatically generated only if you don't specify a specific name.
+ *
+ * @return Name of the field to lock on (blank = generate one).
*/
String value() default "";
}
diff --git a/src/core/lombok/ToString.java b/src/core/lombok/ToString.java
index b9926148..18c3d9e3 100644
--- a/src/core/lombok/ToString.java
+++ b/src/core/lombok/ToString.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009-2013 The Project Lombok Authors.
+ * Copyright (C) 2009-2017 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
@@ -29,7 +29,7 @@ import java.lang.annotation.Target;
/**
* Generates an implementation for the {@code toString} method inherited by all objects, consisting of printing the values of relevant fields.
* <p>
- * Complete documentation is found at <a href="https://projectlombok.org/features/ToString.html">the project lombok features page for &#64;ToString</a>.
+ * Complete documentation is found at <a href="https://projectlombok.org/features/ToString">the project lombok features page for &#64;ToString</a>.
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.SOURCE)
@@ -37,12 +37,16 @@ public @interface ToString {
/**
* Include the name of each field when printing it.
* <strong>default: true</strong>
+ *
+ * @return Whether or not to include the names of fields in the string produced by the generated {@code toString()}.
*/
boolean includeFieldNames() default true;
/**
* Any fields listed here will not be printed in the generated {@code toString} implementation.
* Mutually exclusive with {@link #of()}.
+ *
+ * @return A list of fields to exclude.
*/
String[] exclude() default {};
@@ -51,18 +55,24 @@ public @interface ToString {
* Normally, all non-static fields are printed.
* <p>
* Mutually exclusive with {@link #exclude()}.
+ *
+ * @return A list of fields to use (<em>default</em>: all of them).
*/
String[] of() default {};
/**
* Include the result of the superclass's implementation of {@code toString} in the output.
* <strong>default: false</strong>
+ *
+ * @return Whether to call the superclass's {@code equals} implementation as part of the generated equals algorithm.
*/
boolean callSuper() default false;
/**
* Normally, if getters are available, those are called. To suppress this and let the generated code use the fields directly, set this to {@code true}.
* <strong>default: false</strong>
+ *
+ * @return If {@code true}, always use direct field access instead of calling the getter method.
*/
boolean doNotUseGetters() default false;
}
diff --git a/src/core/lombok/Value.java b/src/core/lombok/Value.java
index 39154226..562ba0cc 100644
--- a/src/core/lombok/Value.java
+++ b/src/core/lombok/Value.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012-2013 The Project Lombok Authors.
+ * Copyright (C) 2012-2017 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
@@ -31,7 +31,7 @@ import java.lang.annotation.Target;
* <p>
* Equivalent to {@code @Getter @FieldDefaults(makeFinal=true, level=AccessLevel.PRIVATE) @AllArgsConstructor @ToString @EqualsAndHashCode}.
* <p>
- * Complete documentation is found at <a href="https://projectlombok.org/features/Value.html">the project lombok features page for &#64;Value</a>.
+ * Complete documentation is found at <a href="https://projectlombok.org/features/Value">the project lombok features page for &#64;Value</a>.
*
* @see lombok.Getter
* @see lombok.experimental.FieldDefaults
@@ -53,6 +53,8 @@ public @interface Value {
* </pre>
*
* Default: No static constructor, instead the normal constructor is public.
+ *
+ * @return Name of static 'constructor' method to generate (blank = generate a normal constructor).
*/
String staticConstructor() default "";
}
diff --git a/src/core/lombok/core/PublicApiCreatorApp.java b/src/core/lombok/core/PublicApiCreatorApp.java
index 178a45e8..c1430c24 100644
--- a/src/core/lombok/core/PublicApiCreatorApp.java
+++ b/src/core/lombok/core/PublicApiCreatorApp.java
@@ -105,7 +105,7 @@ public class PublicApiCreatorApp extends LombokApp {
int firstSlash = subName.indexOf('/');
if (firstSlash == -1) {
// direct member of the lombok package.
- toCopy.add(name);
+ if (!subName.startsWith("ConfigurationKeys")) toCopy.add(name);
continue;
}
String topPkg = subName.substring(0, firstSlash);
diff --git a/src/core/lombok/core/Version.java b/src/core/lombok/core/Version.java
index a50b72d5..18c78b04 100644
--- a/src/core/lombok/core/Version.java
+++ b/src/core/lombok/core/Version.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009-2016 The Project Lombok Authors.
+ * Copyright (C) 2009-2017 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,9 +30,15 @@ public class Version {
// ** CAREFUL ** - this class must always compile with 0 dependencies (it must not refer to any other sources or libraries).
// Note: In 'X.Y.Z', if Z is odd, its a snapshot build built from the repository, so many different 0.10.3 versions can exist, for example.
// Official builds always end in an even number. (Since 0.10.2).
- private static final String VERSION = "1.16.15";
+ private static final String VERSION = "1.16.19";
private static final String RELEASE_NAME = "Edgy Guinea Pig";
-// private static final String RELEASE_NAME = "Candid Duck";
+// private static final String RELEASE_NAME = "Dancing Elephant";
+
+ // Named version history:
+ // Angry Butterfly
+ // Branching Cobra
+ // Candid Duck
+ // Dancing Elephant
private Version() {
//Prevent instantiation
@@ -43,7 +49,7 @@ public class Version {
*/
public static void main(String[] args) {
if (args.length > 0) {
- System.out.printf("Lombok %s\n", getFullVersion());
+ System.out.printf("%s\n", getFullVersion());
} else {
System.out.println(VERSION);
}
diff --git a/src/core/lombok/core/handlers/singulars.txt b/src/core/lombok/core/handlers/singulars.txt
index 9976c76c..d77308cb 100644
--- a/src/core/lombok/core/handlers/singulars.txt
+++ b/src/core/lombok/core/handlers/singulars.txt
@@ -19,7 +19,7 @@ Mice = mouse
Lice = louse
News = !
# We could add more detail (axemen, boatsmen, boogymen, cavemen, gentlemen, etc, but (A) there's stuff like 'cerumen', and (B) the 'men' ending is common in singulars and other languages.)
-# Therefore, the odds of a mistake are too high, so other than these 2 well known cases, so force the explicit singular.
+# Therefore, the odds of a mistake are too high, so other than these 2 well known cases, force the explicit singular.
Men = man
Women = woman
minutiae = minutia
@@ -48,7 +48,9 @@ hives = hive
-shes = sh
-lves = lf
-rves = rf
--ves = fe
+saves = save
+Leaves = leaf
+-ves = !
-ss = !
-us = !
-s =
diff --git a/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java b/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java
index 4726b17e..f49fff7f 100644
--- a/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java
+++ b/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java
@@ -167,6 +167,7 @@ public class EclipseHandlerUtil {
}
public static boolean isFieldDeprecated(EclipseNode fieldNode) {
+ if (!(fieldNode.get() instanceof FieldDeclaration)) return false;
FieldDeclaration field = (FieldDeclaration) fieldNode.get();
if ((field.modifiers & ClassFileConstants.AccDeprecated) != 0) {
return true;
@@ -443,6 +444,24 @@ public class EclipseHandlerUtil {
}
}
+ public static EclipseNode findAnnotation(Class<? extends java.lang.annotation.Annotation> type, EclipseNode node) {
+ if (node == null) return null;
+ if (type == null) return null;
+ switch (node.getKind()) {
+ case ARGUMENT:
+ case FIELD:
+ case LOCAL:
+ case TYPE:
+ case METHOD:
+ for (EclipseNode child : node.down()) {
+ if (annotationTypeMatches(type, child)) return child;
+ }
+ // intentional fallthrough
+ default:
+ return null;
+ }
+ }
+
/**
* Checks if the provided annotation type is likely to be the intended type for the given annotation node.
*
diff --git a/src/core/lombok/eclipse/handlers/EclipseSingularsRecipes.java b/src/core/lombok/eclipse/handlers/EclipseSingularsRecipes.java
index 4cb41d4f..bc779dab 100644
--- a/src/core/lombok/eclipse/handlers/EclipseSingularsRecipes.java
+++ b/src/core/lombok/eclipse/handlers/EclipseSingularsRecipes.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2015 The Project Lombok Authors.
+ * Copyright (C) 2015-2017 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
@@ -132,6 +132,10 @@ public class EclipseSingularsRecipes {
}
}
+ public ASTNode getSource() {
+ return source;
+ }
+
public EclipseNode getAnnotation() {
return annotation;
}
@@ -211,7 +215,7 @@ public class EclipseSingularsRecipes {
}
public abstract List<EclipseNode> generateFields(SingularData data, EclipseNode builderType);
- public abstract void generateMethods(SingularData data, EclipseNode builderType, boolean fluent, boolean chain);
+ public abstract void generateMethods(SingularData data, boolean deprecate, EclipseNode builderType, boolean fluent, boolean chain);
public abstract void appendBuildCode(SingularData data, EclipseNode builderType, List<Statement> statements, char[] targetVariableName);
public boolean requiresCleaning() {
diff --git a/src/core/lombok/eclipse/handlers/HandleBuilder.java b/src/core/lombok/eclipse/handlers/HandleBuilder.java
index 8c200a94..5f2e8fe3 100644
--- a/src/core/lombok/eclipse/handlers/HandleBuilder.java
+++ b/src/core/lombok/eclipse/handlers/HandleBuilder.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013-2015 The Project Lombok Authors.
+ * Copyright (C) 2013-2017 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
@@ -38,6 +38,7 @@ import org.eclipse.jdt.internal.compiler.ast.Annotation;
import org.eclipse.jdt.internal.compiler.ast.Argument;
import org.eclipse.jdt.internal.compiler.ast.Assignment;
import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.ConditionalExpression;
import org.eclipse.jdt.internal.compiler.ast.ConstructorDeclaration;
import org.eclipse.jdt.internal.compiler.ast.Expression;
import org.eclipse.jdt.internal.compiler.ast.FalseLiteral;
@@ -102,9 +103,12 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
TypeReference type;
char[] rawName;
char[] name;
+ char[] nameOfDefaultProvider;
+ char[] nameOfSetFlag;
SingularData singularData;
ObtainVia obtainVia;
EclipseNode obtainViaNode;
+ EclipseNode originalFieldNode;
List<EclipseNode> createdFields = new ArrayList<EclipseNode>();
}
@@ -127,6 +131,16 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
return true;
}
+ private static final char[] DEFAULT_PREFIX = {'$', 'd', 'e', 'f', 'a', 'u', 'l', 't', '$'};
+ private static final char[] SET_PREFIX = {'$', 's', 'e', 't'};
+
+ private static final char[] prefixWith(char[] prefix, char[] name) {
+ char[] out = new char[prefix.length + name.length];
+ System.arraycopy(prefix, 0, out, 0, prefix.length);
+ System.arraycopy(name, 0, out, prefix.length, name.length);
+ return out;
+ }
+
@Override public void handle(AnnotationValues<Builder> annotation, Annotation ast, EclipseNode annotationNode) {
long p = (long) ast.sourceStart << 32 | ast.sourceEnd;
@@ -173,17 +187,40 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
List<EclipseNode> allFields = new ArrayList<EclipseNode>();
@SuppressWarnings("deprecation")
boolean valuePresent = (hasAnnotation(lombok.Value.class, parent) || hasAnnotation(lombok.experimental.Value.class, parent));
- for (EclipseNode fieldNode : HandleConstructor.findAllFields(tdParent)) {
+ for (EclipseNode fieldNode : HandleConstructor.findAllFields(tdParent, true)) {
FieldDeclaration fd = (FieldDeclaration) fieldNode.get();
- // final fields with an initializer cannot be written to, so they can't be 'builderized'. Unfortunately presence of @Value makes
- // non-final fields final, but @Value's handler hasn't done this yet, so we have to do this math ourselves.
- // Value will only skip making a field final if it has an explicit @NonFinal annotation, so we check for that.
- if (fd.initialization != null && valuePresent && !hasAnnotation(NonFinal.class, fieldNode)) continue;
+ EclipseNode isDefault = findAnnotation(Builder.Default.class, fieldNode);
+ boolean isFinal = ((fd.modifiers & ClassFileConstants.AccFinal) != 0) || (valuePresent && !hasAnnotation(NonFinal.class, fieldNode));
+
BuilderFieldData bfd = new BuilderFieldData();
bfd.rawName = fieldNode.getName().toCharArray();
bfd.name = removePrefixFromField(fieldNode);
bfd.type = fd.type;
bfd.singularData = getSingularData(fieldNode, ast);
+ bfd.originalFieldNode = fieldNode;
+
+ if (bfd.singularData != null && isDefault != null) {
+ isDefault.addError("@Builder.Default and @Singular cannot be mixed.");
+ isDefault = null;
+ }
+
+ if (fd.initialization == null && isDefault != null) {
+ isDefault.addWarning("@Builder.Default requires an initializing expression (' = something;').");
+ isDefault = null;
+ }
+
+ if (fd.initialization != null && isDefault == null) {
+ if (isFinal) continue;
+ fieldNode.addWarning("@Builder will ignore the initializing expression entirely. If you want the initializing expression to serve as default, add @Builder.Default. If it is not supposed to be settable during building, make the field final.");
+ }
+
+ if (isDefault != null) {
+ bfd.nameOfDefaultProvider = prefixWith(DEFAULT_PREFIX, bfd.name);
+ bfd.nameOfSetFlag = prefixWith(bfd.name, SET_PREFIX);
+
+ MethodDeclaration md = generateDefaultProvider(bfd.nameOfDefaultProvider, fieldNode, ast);
+ if (md != null) injectMethod(tdParent, md);
+ }
addObtainVia(bfd, fieldNode);
builderFields.add(bfd);
allFields.add(fieldNode);
@@ -334,6 +371,7 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
bfd.name = arg.name;
bfd.type = arg.type;
bfd.singularData = getSingularData(param, ast);
+ bfd.originalFieldNode = param;
addObtainVia(bfd, param);
builderFields.add(bfd);
}
@@ -405,7 +443,7 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
}
if (methodExists(buildMethodName, builderType, -1) == MemberExistsResult.NOT_EXISTS) {
- MethodDeclaration md = generateBuildMethod(isStatic, buildMethodName, nameOfStaticBuilderMethod, returnType, builderFields, builderType, thrownExceptions, addCleaning, ast);
+ MethodDeclaration md = generateBuildMethod(tdParent, isStatic, buildMethodName, nameOfStaticBuilderMethod, returnType, builderFields, builderType, thrownExceptions, addCleaning, ast);
if (md != null) injectMethod(builderType, md);
}
@@ -514,7 +552,7 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
return decl;
}
- public MethodDeclaration generateBuildMethod(boolean isStatic, String name, char[] staticName, TypeReference returnType, List<BuilderFieldData> builderFields, EclipseNode type, TypeReference[] thrownExceptions, boolean addCleaning, ASTNode source) {
+ public MethodDeclaration generateBuildMethod(EclipseNode tdParent, boolean isStatic, String name, char[] staticName, TypeReference returnType, List<BuilderFieldData> builderFields, EclipseNode type, TypeReference[] thrownExceptions, boolean addCleaning, ASTNode source) {
MethodDeclaration out = new MethodDeclaration(((CompilationUnitDeclaration) type.top().get()).compilationResult);
out.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG;
List<Statement> statements = new ArrayList<Statement>();
@@ -536,7 +574,20 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
List<Expression> args = new ArrayList<Expression>();
for (BuilderFieldData bfd : builderFields) {
- args.add(new SingleNameReference(bfd.name, 0L));
+ if (bfd.nameOfSetFlag != null) {
+ MessageSend inv = new MessageSend();
+ inv.sourceStart = source.sourceStart;
+ inv.sourceEnd = source.sourceEnd;
+ inv.receiver = new SingleNameReference(((TypeDeclaration) tdParent.get()).name, 0L);
+ inv.selector = bfd.nameOfDefaultProvider;
+
+ args.add(new ConditionalExpression(
+ new SingleNameReference(bfd.nameOfSetFlag, 0L),
+ new SingleNameReference(bfd.name, 0L),
+ inv));
+ } else {
+ args.add(new SingleNameReference(bfd.name, 0L));
+ }
}
if (addCleaning) {
@@ -583,6 +634,22 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
return out;
}
+ public MethodDeclaration generateDefaultProvider(char[] methodName, EclipseNode fieldNode, ASTNode source) {
+ int pS = source.sourceStart, pE = source.sourceEnd;
+
+ MethodDeclaration out = new MethodDeclaration(((CompilationUnitDeclaration) fieldNode.top().get()).compilationResult);
+ out.selector = methodName;
+ out.modifiers = ClassFileConstants.AccPrivate | ClassFileConstants.AccStatic;
+ out.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG;
+ FieldDeclaration fd = (FieldDeclaration) fieldNode.get();
+ out.returnType = copyType(fd.type, source);
+ out.statements = new Statement[] {new ReturnStatement(fd.initialization, pS, pE)};
+ fd.initialization = null;
+
+ out.traverse(new SetGeneratedByVisitor(source), ((TypeDeclaration) fieldNode.up().get()).scope);
+ return out;
+ }
+
public MethodDeclaration generateBuilderMethod(boolean isStatic, String builderMethodName, String builderClassName, EclipseNode type, TypeParameter[] typeParams, ASTNode source) {
int pS = source.sourceStart, pE = source.sourceEnd;
long p = (long) pS << 32 | pE;
@@ -608,25 +675,34 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
if (child.getKind() == Kind.FIELD) existing.add(child);
}
- top:
for (BuilderFieldData bfd : builderFields) {
if (bfd.singularData != null && bfd.singularData.getSingularizer() != null) {
bfd.createdFields.addAll(bfd.singularData.getSingularizer().generateFields(bfd.singularData, builderType));
} else {
+ EclipseNode field = null, setFlag = null;
for (EclipseNode exists : existing) {
char[] n = ((FieldDeclaration) exists.get()).name;
- if (Arrays.equals(n, bfd.name)) {
- bfd.createdFields.add(exists);
- continue top;
- }
+ if (Arrays.equals(n, bfd.name)) field = exists;
+ if (bfd.nameOfSetFlag != null && Arrays.equals(n, bfd.nameOfSetFlag)) setFlag = exists;
}
- FieldDeclaration fd = new FieldDeclaration(bfd.name, 0, 0);
- fd.bits |= Eclipse.ECLIPSE_DO_NOT_TOUCH_FLAG;
- fd.modifiers = ClassFileConstants.AccPrivate;
- fd.type = copyType(bfd.type);
- fd.traverse(new SetGeneratedByVisitor(source), (MethodScope) null);
- bfd.createdFields.add(injectFieldAndMarkGenerated(builderType, fd));
+ if (field == null) {
+ FieldDeclaration fd = new FieldDeclaration(bfd.name, 0, 0);
+ fd.bits |= Eclipse.ECLIPSE_DO_NOT_TOUCH_FLAG;
+ fd.modifiers = ClassFileConstants.AccPrivate;
+ fd.type = copyType(bfd.type);
+ fd.traverse(new SetGeneratedByVisitor(source), (MethodScope) null);
+ field = injectFieldAndMarkGenerated(builderType, fd);
+ }
+ if (setFlag == null && bfd.nameOfSetFlag != null) {
+ FieldDeclaration fd = new FieldDeclaration(bfd.nameOfSetFlag, 0, 0);
+ fd.bits |= Eclipse.ECLIPSE_DO_NOT_TOUCH_FLAG;
+ fd.modifiers = ClassFileConstants.AccPrivate;
+ fd.type = TypeReference.baseTypeReference(TypeIds.T_boolean, 0);
+ fd.traverse(new SetGeneratedByVisitor(source), (MethodScope) null);
+ injectFieldAndMarkGenerated(builderType, fd);
+ }
+ bfd.createdFields.add(field);
}
}
}
@@ -634,14 +710,15 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
private static final AbstractMethodDeclaration[] EMPTY = {};
public void makeSetterMethodsForBuilder(EclipseNode builderType, BuilderFieldData bfd, EclipseNode sourceNode, boolean fluent, boolean chain) {
+ boolean deprecate = isFieldDeprecated(bfd.originalFieldNode);
if (bfd.singularData == null || bfd.singularData.getSingularizer() == null) {
- makeSimpleSetterMethodForBuilder(builderType, bfd.createdFields.get(0), sourceNode, fluent, chain);
+ makeSimpleSetterMethodForBuilder(builderType, deprecate, bfd.createdFields.get(0), bfd.nameOfSetFlag, sourceNode, fluent, chain);
} else {
- bfd.singularData.getSingularizer().generateMethods(bfd.singularData, builderType, fluent, chain);
+ bfd.singularData.getSingularizer().generateMethods(bfd.singularData, deprecate, builderType, fluent, chain);
}
}
- private void makeSimpleSetterMethodForBuilder(EclipseNode builderType, EclipseNode fieldNode, EclipseNode sourceNode, boolean fluent, boolean chain) {
+ private void makeSimpleSetterMethodForBuilder(EclipseNode builderType, boolean deprecate, EclipseNode fieldNode, char[] nameOfSetFlag, EclipseNode sourceNode, boolean fluent, boolean chain) {
TypeDeclaration td = (TypeDeclaration) builderType.get();
AbstractMethodDeclaration[] existing = td.methods;
if (existing == null) existing = EMPTY;
@@ -657,7 +734,7 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
String setterName = fluent ? fieldNode.getName() : HandlerUtil.buildAccessorName("set", fieldNode.getName());
- MethodDeclaration setter = HandleSetter.createSetter(td, fieldNode, setterName, chain, ClassFileConstants.AccPublic,
+ MethodDeclaration setter = HandleSetter.createSetter(td, deprecate, fieldNode, setterName, nameOfSetFlag, chain, ClassFileConstants.AccPublic,
sourceNode, Collections.<Annotation>emptyList(), Collections.<Annotation>emptyList());
injectMethod(builderType, setter);
}
diff --git a/src/core/lombok/eclipse/handlers/HandleBuilderDefault.java b/src/core/lombok/eclipse/handlers/HandleBuilderDefault.java
new file mode 100644
index 00000000..da184d0b
--- /dev/null
+++ b/src/core/lombok/eclipse/handlers/HandleBuilderDefault.java
@@ -0,0 +1,25 @@
+package lombok.eclipse.handlers;
+
+import static lombok.eclipse.handlers.EclipseHandlerUtil.*;
+import org.eclipse.jdt.internal.compiler.ast.Annotation;
+import org.mangosdk.spi.ProviderFor;
+
+import lombok.Builder;
+import lombok.core.AST.Kind;
+import lombok.core.AnnotationValues;
+import lombok.core.HandlerPriority;
+import lombok.eclipse.EclipseAnnotationHandler;
+import lombok.eclipse.EclipseNode;
+
+@ProviderFor(EclipseAnnotationHandler.class)
+@HandlerPriority(-1025) //HandleBuilder's level, minus one.
+public class HandleBuilderDefault extends EclipseAnnotationHandler<Builder.Default> {
+ @Override public void handle(AnnotationValues<Builder.Default> annotation, Annotation ast, EclipseNode annotationNode) {
+ EclipseNode annotatedField = annotationNode.up();
+ if (annotatedField.getKind() != Kind.FIELD) return;
+ EclipseNode classWithAnnotatedField = annotatedField.up();
+ if (!hasAnnotation(Builder.class, classWithAnnotatedField)) {
+ annotationNode.addWarning("@Builder.Default requires @Builder on the class for it to mean anything.");
+ }
+ }
+}
diff --git a/src/core/lombok/eclipse/handlers/HandleConstructor.java b/src/core/lombok/eclipse/handlers/HandleConstructor.java
index 072b6dd5..3469e6bf 100644
--- a/src/core/lombok/eclipse/handlers/HandleConstructor.java
+++ b/src/core/lombok/eclipse/handlers/HandleConstructor.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010-2015 The Project Lombok Authors.
+ * Copyright (C) 2010-2017 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
@@ -144,14 +144,17 @@ public class HandleConstructor {
}
static List<EclipseNode> findAllFields(EclipseNode typeNode) {
+ return findAllFields(typeNode, false);
+ }
+
+ static List<EclipseNode> findAllFields(EclipseNode typeNode, boolean evenFinalInitialized) {
List<EclipseNode> fields = new ArrayList<EclipseNode>();
for (EclipseNode child : typeNode.down()) {
if (child.getKind() != Kind.FIELD) continue;
FieldDeclaration fieldDecl = (FieldDeclaration) child.get();
if (!filterField(fieldDecl)) continue;
- // Skip initialized final fields.
- if (((fieldDecl.modifiers & ClassFileConstants.AccFinal) != 0) && fieldDecl.initialization != null) continue;
+ if (!evenFinalInitialized && ((fieldDecl.modifiers & ClassFileConstants.AccFinal) != 0) && fieldDecl.initialization != null) continue;
fields.add(child);
}
@@ -361,7 +364,7 @@ public class HandleConstructor {
/* Generate annotations that must be put on the generated method, and attach them. */ {
Annotation[] constructorProperties = null;
- if (!allToDefault && !suppressConstructorProperties && level != AccessLevel.PRIVATE && level != AccessLevel.PACKAGE && !isLocalType(type)) {
+ if (!allToDefault && !suppressConstructorProperties && !isLocalType(type)) {
constructorProperties = createConstructorProperties(source, fields);
}
diff --git a/src/core/lombok/eclipse/handlers/HandleEqualsAndHashCode.java b/src/core/lombok/eclipse/handlers/HandleEqualsAndHashCode.java
index ceef3d3c..37fa78ab 100644
--- a/src/core/lombok/eclipse/handlers/HandleEqualsAndHashCode.java
+++ b/src/core/lombok/eclipse/handlers/HandleEqualsAndHashCode.java
@@ -118,7 +118,10 @@ public class HandleEqualsAndHashCode extends EclipseAnnotationHandler<EqualsAndH
return;
}
- generateMethods(typeNode, errorNode, null, null, null, false, FieldAccess.GETTER, new ArrayList<Annotation>());
+ Boolean doNotUseGettersConfiguration = typeNode.getAst().readConfiguration(ConfigurationKeys.EQUALS_AND_HASH_CODE_DO_NOT_USE_GETTERS);
+ FieldAccess access = doNotUseGettersConfiguration == null || !doNotUseGettersConfiguration ? FieldAccess.GETTER : FieldAccess.PREFER_FIELD;
+
+ generateMethods(typeNode, errorNode, null, null, null, false, access, new ArrayList<Annotation>());
}
@Override public void handle(AnnotationValues<EqualsAndHashCode> annotation, Annotation ast, EclipseNode annotationNode) {
diff --git a/src/core/lombok/eclipse/handlers/HandleSetter.java b/src/core/lombok/eclipse/handlers/HandleSetter.java
index 7e7ea121..6a9a5123 100644
--- a/src/core/lombok/eclipse/handlers/HandleSetter.java
+++ b/src/core/lombok/eclipse/handlers/HandleSetter.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009-2014 The Project Lombok Authors.
+ * Copyright (C) 2009-2017 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,7 @@ import org.eclipse.jdt.internal.compiler.ast.ReturnStatement;
import org.eclipse.jdt.internal.compiler.ast.SingleNameReference;
import org.eclipse.jdt.internal.compiler.ast.Statement;
import org.eclipse.jdt.internal.compiler.ast.ThisReference;
+import org.eclipse.jdt.internal.compiler.ast.TrueLiteral;
import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
import org.eclipse.jdt.internal.compiler.ast.TypeReference;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
@@ -192,11 +193,11 @@ public class HandleSetter extends EclipseAnnotationHandler<Setter> {
}
}
- MethodDeclaration method = createSetter((TypeDeclaration) fieldNode.up().get(), fieldNode, setterName, shouldReturnThis, modifier, sourceNode, onMethod, onParam);
+ MethodDeclaration method = createSetter((TypeDeclaration) fieldNode.up().get(), false, fieldNode, setterName, null, shouldReturnThis, modifier, sourceNode, onMethod, onParam);
injectMethod(fieldNode.up(), method);
}
- static MethodDeclaration createSetter(TypeDeclaration parent, EclipseNode fieldNode, String name, boolean shouldReturnThis, int modifier, EclipseNode sourceNode, List<Annotation> onMethod, List<Annotation> onParam) {
+ static MethodDeclaration createSetter(TypeDeclaration parent, boolean deprecate, EclipseNode fieldNode, String name, char[] booleanFieldToSet, boolean shouldReturnThis, int modifier, EclipseNode sourceNode, List<Annotation> onMethod, List<Annotation> onParam) {
FieldDeclaration field = (FieldDeclaration) fieldNode.get();
ASTNode source = sourceNode.get();
int pS = source.sourceStart, pE = source.sourceEnd;
@@ -213,7 +214,7 @@ public class HandleSetter extends EclipseAnnotationHandler<Setter> {
shouldReturnThis = false;
}
Annotation[] deprecated = null;
- if (isFieldDeprecated(fieldNode)) {
+ if (isFieldDeprecated(fieldNode) || deprecate) {
deprecated = new Annotation[] { generateDeprecatedAnnotation(source) };
}
method.annotations = copyAnnotations(source, onMethod.toArray(new Annotation[0]), deprecated);
@@ -243,6 +244,10 @@ public class HandleSetter extends EclipseAnnotationHandler<Setter> {
statements.add(assignment);
}
+ if (booleanFieldToSet != null) {
+ statements.add(new Assignment(new SingleNameReference(booleanFieldToSet, p), new TrueLiteral(pS, pE), pE));
+ }
+
if (shouldReturnThis) {
ThisReference thisRef = new ThisReference(pS, pE);
ReturnStatement returnThis = new ReturnStatement(thisRef, pS, pE);
diff --git a/src/core/lombok/eclipse/handlers/HandleToString.java b/src/core/lombok/eclipse/handlers/HandleToString.java
index a4ed254a..d8f4c569 100644
--- a/src/core/lombok/eclipse/handlers/HandleToString.java
+++ b/src/core/lombok/eclipse/handlers/HandleToString.java
@@ -94,7 +94,11 @@ public class HandleToString extends EclipseAnnotationHandler<ToString> {
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);
+
+ Boolean doNotUseGettersConfiguration = typeNode.getAst().readConfiguration(ConfigurationKeys.TO_STRING_DO_NOT_USE_GETTERS);
+ FieldAccess access = doNotUseGettersConfiguration == null || !doNotUseGettersConfiguration ? FieldAccess.GETTER : FieldAccess.PREFER_FIELD;
+
+ generateToString(typeNode, errorNode, null, null, includeFieldNames, null, false, access);
}
public void handle(AnnotationValues<ToString> annotation, Annotation ast, EclipseNode annotationNode) {
diff --git a/src/core/lombok/eclipse/handlers/singulars/EclipseGuavaSingularizer.java b/src/core/lombok/eclipse/handlers/singulars/EclipseGuavaSingularizer.java
index 242bde1f..8e925b3f 100644
--- a/src/core/lombok/eclipse/handlers/singulars/EclipseGuavaSingularizer.java
+++ b/src/core/lombok/eclipse/handlers/singulars/EclipseGuavaSingularizer.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2015 The Project Lombok Authors.
+ * Copyright (C) 2015-2017 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
@@ -35,6 +35,7 @@ import lombok.eclipse.EclipseNode;
import lombok.eclipse.handlers.EclipseSingularsRecipes.EclipseSingularizer;
import lombok.eclipse.handlers.EclipseSingularsRecipes.SingularData;
+import org.eclipse.jdt.internal.compiler.ast.Annotation;
import org.eclipse.jdt.internal.compiler.ast.Argument;
import org.eclipse.jdt.internal.compiler.ast.Assignment;
import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
@@ -96,21 +97,21 @@ abstract class EclipseGuavaSingularizer extends EclipseSingularizer {
return Collections.singletonList(injectFieldAndMarkGenerated(builderType, buildField));
}
- @Override public void generateMethods(SingularData data, EclipseNode builderType, boolean fluent, boolean chain) {
+ @Override public void generateMethods(SingularData data, boolean deprecate, EclipseNode builderType, boolean fluent, boolean chain) {
TypeReference returnType = chain ? cloneSelfType(builderType) : TypeReference.baseTypeReference(TypeIds.T_void, 0);
Statement returnStatement = chain ? new ReturnStatement(new ThisReference(0, 0), 0, 0) : null;
- generateSingularMethod(returnType, returnStatement, data, builderType, fluent);
+ generateSingularMethod(deprecate, returnType, returnStatement, data, builderType, fluent);
returnType = chain ? cloneSelfType(builderType) : TypeReference.baseTypeReference(TypeIds.T_void, 0);
returnStatement = chain ? new ReturnStatement(new ThisReference(0, 0), 0, 0) : null;
- generatePluralMethod(returnType, returnStatement, data, builderType, fluent);
+ generatePluralMethod(deprecate, returnType, returnStatement, data, builderType, fluent);
returnType = chain ? cloneSelfType(builderType) : TypeReference.baseTypeReference(TypeIds.T_void, 0);
returnStatement = chain ? new ReturnStatement(new ThisReference(0, 0), 0, 0) : null;
- generateClearMethod(returnType, returnStatement, data, builderType);
+ generateClearMethod(deprecate, returnType, returnStatement, data, builderType);
}
- void generateClearMethod(TypeReference returnType, Statement returnStatement, SingularData data, EclipseNode builderType) {
+ void generateClearMethod(boolean deprecate, TypeReference returnType, Statement returnStatement, SingularData data, EclipseNode builderType) {
MethodDeclaration md = new MethodDeclaration(((CompilationUnitDeclaration) builderType.top().get()).compilationResult);
md.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG;
md.modifiers = ClassFileConstants.AccPublic;
@@ -121,10 +122,12 @@ abstract class EclipseGuavaSingularizer extends EclipseSingularizer {
md.selector = HandlerUtil.buildAccessorName("clear", new String(data.getPluralName())).toCharArray();
md.statements = returnStatement != null ? new Statement[] {a, returnStatement} : new Statement[] {a};
md.returnType = returnType;
+ md.annotations = deprecate ? new Annotation[] { generateDeprecatedAnnotation(data.getSource()) } : null;
+
injectMethod(builderType, md);
}
- void generateSingularMethod(TypeReference returnType, Statement returnStatement, SingularData data, EclipseNode builderType, boolean fluent) {
+ void generateSingularMethod(boolean deprecate, TypeReference returnType, Statement returnStatement, SingularData data, EclipseNode builderType, boolean fluent) {
LombokImmutableList<String> suffixes = getArgumentSuffixes();
char[][] names = new char[suffixes.size()][];
for (int i = 0; i < suffixes.size(); i++) {
@@ -159,12 +162,13 @@ abstract class EclipseGuavaSingularizer extends EclipseSingularizer {
}
md.returnType = returnType;
md.selector = fluent ? data.getSingularName() : HandlerUtil.buildAccessorName(getAddMethodName(), new String(data.getSingularName())).toCharArray();
+ md.annotations = deprecate ? new Annotation[] { generateDeprecatedAnnotation(data.getSource()) } : null;
data.setGeneratedByRecursive(md);
injectMethod(builderType, md);
}
- void generatePluralMethod(TypeReference returnType, Statement returnStatement, SingularData data, EclipseNode builderType, boolean fluent) {
+ void generatePluralMethod(boolean deprecate, TypeReference returnType, Statement returnStatement, SingularData data, EclipseNode builderType, boolean fluent) {
MethodDeclaration md = new MethodDeclaration(((CompilationUnitDeclaration) builderType.top().get()).compilationResult);
md.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG;
md.modifiers = ClassFileConstants.AccPublic;
@@ -190,6 +194,7 @@ abstract class EclipseGuavaSingularizer extends EclipseSingularizer {
md.arguments = new Argument[] {param};
md.returnType = returnType;
md.selector = fluent ? data.getPluralName() : HandlerUtil.buildAccessorName(getAddMethodName() + "All", new String(data.getPluralName())).toCharArray();
+ md.annotations = deprecate ? new Annotation[] { generateDeprecatedAnnotation(data.getSource()) } : null;
data.setGeneratedByRecursive(md);
injectMethod(builderType, md);
diff --git a/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilListSetSingularizer.java b/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilListSetSingularizer.java
index 2d8083d3..cfa48eaf 100644
--- a/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilListSetSingularizer.java
+++ b/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilListSetSingularizer.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2015 The Project Lombok Authors.
+ * Copyright (C) 2015-2017 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
@@ -32,6 +32,7 @@ import lombok.core.handlers.HandlerUtil;
import lombok.eclipse.EclipseNode;
import lombok.eclipse.handlers.EclipseSingularsRecipes.SingularData;
+import org.eclipse.jdt.internal.compiler.ast.Annotation;
import org.eclipse.jdt.internal.compiler.ast.Argument;
import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
import org.eclipse.jdt.internal.compiler.ast.EqualExpression;
@@ -87,26 +88,26 @@ abstract class EclipseJavaUtilListSetSingularizer extends EclipseJavaUtilSingula
return Collections.singletonList(injectFieldAndMarkGenerated(builderType, buildField));
}
- @Override public void generateMethods(SingularData data, EclipseNode builderType, boolean fluent, boolean chain) {
+ @Override public void generateMethods(SingularData data, boolean deprecate, EclipseNode builderType, boolean fluent, boolean chain) {
if (useGuavaInstead(builderType)) {
- guavaListSetSingularizer.generateMethods(data, builderType, fluent, chain);
+ guavaListSetSingularizer.generateMethods(data, deprecate, builderType, fluent, chain);
return;
}
TypeReference returnType = chain ? cloneSelfType(builderType) : TypeReference.baseTypeReference(TypeIds.T_void, 0);
Statement returnStatement = chain ? new ReturnStatement(new ThisReference(0, 0), 0, 0) : null;
- generateSingularMethod(returnType, returnStatement, data, builderType, fluent);
+ generateSingularMethod(deprecate, returnType, returnStatement, data, builderType, fluent);
returnType = chain ? cloneSelfType(builderType) : TypeReference.baseTypeReference(TypeIds.T_void, 0);
returnStatement = chain ? new ReturnStatement(new ThisReference(0, 0), 0, 0) : null;
- generatePluralMethod(returnType, returnStatement, data, builderType, fluent);
+ generatePluralMethod(deprecate, returnType, returnStatement, data, builderType, fluent);
returnType = chain ? cloneSelfType(builderType) : TypeReference.baseTypeReference(TypeIds.T_void, 0);
returnStatement = chain ? new ReturnStatement(new ThisReference(0, 0), 0, 0) : null;
- generateClearMethod(returnType, returnStatement, data, builderType);
+ generateClearMethod(deprecate, returnType, returnStatement, data, builderType);
}
- private void generateClearMethod(TypeReference returnType, Statement returnStatement, SingularData data, EclipseNode builderType) {
+ private void generateClearMethod(boolean deprecate, TypeReference returnType, Statement returnStatement, SingularData data, EclipseNode builderType) {
MethodDeclaration md = new MethodDeclaration(((CompilationUnitDeclaration) builderType.top().get()).compilationResult);
md.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG;
md.modifiers = ClassFileConstants.AccPublic;
@@ -122,10 +123,11 @@ abstract class EclipseJavaUtilListSetSingularizer extends EclipseJavaUtilSingula
Statement clearStatement = new IfStatement(new EqualExpression(thisDotField, new NullLiteral(0, 0), OperatorIds.NOT_EQUAL), clearMsg, 0, 0);
md.statements = returnStatement != null ? new Statement[] {clearStatement, returnStatement} : new Statement[] {clearStatement};
md.returnType = returnType;
+ md.annotations = deprecate ? new Annotation[] { generateDeprecatedAnnotation(data.getSource()) } : null;
injectMethod(builderType, md);
}
- void generateSingularMethod(TypeReference returnType, Statement returnStatement, SingularData data, EclipseNode builderType, boolean fluent) {
+ void generateSingularMethod(boolean deprecate, TypeReference returnType, Statement returnStatement, SingularData data, EclipseNode builderType, boolean fluent) {
MethodDeclaration md = new MethodDeclaration(((CompilationUnitDeclaration) builderType.top().get()).compilationResult);
md.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG;
md.modifiers = ClassFileConstants.AccPublic;
@@ -148,12 +150,13 @@ abstract class EclipseJavaUtilListSetSingularizer extends EclipseJavaUtilSingula
md.arguments = new Argument[] {param};
md.returnType = returnType;
md.selector = fluent ? data.getSingularName() : HandlerUtil.buildAccessorName("add", new String(data.getSingularName())).toCharArray();
+ md.annotations = deprecate ? new Annotation[] { generateDeprecatedAnnotation(data.getSource()) } : null;
data.setGeneratedByRecursive(md);
injectMethod(builderType, md);
}
- void generatePluralMethod(TypeReference returnType, Statement returnStatement, SingularData data, EclipseNode builderType, boolean fluent) {
+ void generatePluralMethod(boolean deprecate, TypeReference returnType, Statement returnStatement, SingularData data, EclipseNode builderType, boolean fluent) {
MethodDeclaration md = new MethodDeclaration(((CompilationUnitDeclaration) builderType.top().get()).compilationResult);
md.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG;
md.modifiers = ClassFileConstants.AccPublic;
@@ -178,6 +181,7 @@ abstract class EclipseJavaUtilListSetSingularizer extends EclipseJavaUtilSingula
md.arguments = new Argument[] {param};
md.returnType = returnType;
md.selector = fluent ? data.getPluralName() : HandlerUtil.buildAccessorName("addAll", new String(data.getPluralName())).toCharArray();
+ md.annotations = deprecate ? new Annotation[] { generateDeprecatedAnnotation(data.getSource()) } : null;
data.setGeneratedByRecursive(md);
injectMethod(builderType, md);
diff --git a/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilMapSingularizer.java b/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilMapSingularizer.java
index ef9e2a76..9aac32a3 100644
--- a/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilMapSingularizer.java
+++ b/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilMapSingularizer.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2015 The Project Lombok Authors.
+ * Copyright (C) 2015-2017 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
@@ -29,6 +29,7 @@ import java.util.Arrays;
import java.util.Collections;
import java.util.List;
+import org.eclipse.jdt.internal.compiler.ast.Annotation;
import org.eclipse.jdt.internal.compiler.ast.Argument;
import org.eclipse.jdt.internal.compiler.ast.Block;
import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
@@ -132,26 +133,26 @@ public class EclipseJavaUtilMapSingularizer extends EclipseJavaUtilSingularizer
return Arrays.asList(keyFieldNode, valueFieldNode);
}
- @Override public void generateMethods(SingularData data, EclipseNode builderType, boolean fluent, boolean chain) {
+ @Override public void generateMethods(SingularData data, boolean deprecate, EclipseNode builderType, boolean fluent, boolean chain) {
if (useGuavaInstead(builderType)) {
- guavaMapSingularizer.generateMethods(data, builderType, fluent, chain);
+ guavaMapSingularizer.generateMethods(data, deprecate, builderType, fluent, chain);
return;
}
TypeReference returnType = chain ? cloneSelfType(builderType) : TypeReference.baseTypeReference(TypeIds.T_void, 0);
Statement returnStatement = chain ? new ReturnStatement(new ThisReference(0, 0), 0, 0) : null;
- generateSingularMethod(returnType, returnStatement, data, builderType, fluent);
+ generateSingularMethod(deprecate, returnType, returnStatement, data, builderType, fluent);
returnType = chain ? cloneSelfType(builderType) : TypeReference.baseTypeReference(TypeIds.T_void, 0);
returnStatement = chain ? new ReturnStatement(new ThisReference(0, 0), 0, 0) : null;
- generatePluralMethod(returnType, returnStatement, data, builderType, fluent);
+ generatePluralMethod(deprecate, returnType, returnStatement, data, builderType, fluent);
returnType = chain ? cloneSelfType(builderType) : TypeReference.baseTypeReference(TypeIds.T_void, 0);
returnStatement = chain ? new ReturnStatement(new ThisReference(0, 0), 0, 0) : null;
- generateClearMethod(returnType, returnStatement, data, builderType);
+ generateClearMethod(deprecate, returnType, returnStatement, data, builderType);
}
- private void generateClearMethod(TypeReference returnType, Statement returnStatement, SingularData data, EclipseNode builderType) {
+ private void generateClearMethod(boolean deprecate, TypeReference returnType, Statement returnStatement, SingularData data, EclipseNode builderType) {
MethodDeclaration md = new MethodDeclaration(((CompilationUnitDeclaration) builderType.top().get()).compilationResult);
md.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG;
md.modifiers = ClassFileConstants.AccPublic;
@@ -178,10 +179,12 @@ public class EclipseJavaUtilMapSingularizer extends EclipseJavaUtilSingularizer
Statement clearStatement = new IfStatement(new EqualExpression(thisDotField, new NullLiteral(0, 0), OperatorIds.NOT_EQUAL), clearMsgs, 0, 0);
md.statements = returnStatement != null ? new Statement[] {clearStatement, returnStatement} : new Statement[] {clearStatement};
md.returnType = returnType;
+ md.annotations = deprecate ? new Annotation[] { generateDeprecatedAnnotation(data.getSource()) } : null;
+
injectMethod(builderType, md);
}
- private void generateSingularMethod(TypeReference returnType, Statement returnStatement, SingularData data, EclipseNode builderType, boolean fluent) {
+ private void generateSingularMethod(boolean deprecate, TypeReference returnType, Statement returnStatement, SingularData data, EclipseNode builderType, boolean fluent) {
MethodDeclaration md = new MethodDeclaration(((CompilationUnitDeclaration) builderType.top().get()).compilationResult);
md.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG;
md.modifiers = ClassFileConstants.AccPublic;
@@ -225,12 +228,13 @@ public class EclipseJavaUtilMapSingularizer extends EclipseJavaUtilSingularizer
md.arguments = new Argument[] {keyParam, valueParam};
md.returnType = returnType;
md.selector = fluent ? data.getSingularName() : HandlerUtil.buildAccessorName("put", new String(data.getSingularName())).toCharArray();
+ md.annotations = deprecate ? new Annotation[] { generateDeprecatedAnnotation(data.getSource()) } : null;
data.setGeneratedByRecursive(md);
injectMethod(builderType, md);
}
- private void generatePluralMethod(TypeReference returnType, Statement returnStatement, SingularData data, EclipseNode builderType, boolean fluent) {
+ private void generatePluralMethod(boolean deprecate, TypeReference returnType, Statement returnStatement, SingularData data, EclipseNode builderType, boolean fluent) {
MethodDeclaration md = new MethodDeclaration(((CompilationUnitDeclaration) builderType.top().get()).compilationResult);
md.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG;
md.modifiers = ClassFileConstants.AccPublic;
@@ -288,6 +292,7 @@ public class EclipseJavaUtilMapSingularizer extends EclipseJavaUtilSingularizer
md.arguments = new Argument[] {param};
md.returnType = returnType;
md.selector = fluent ? data.getPluralName() : HandlerUtil.buildAccessorName("putAll", new String(data.getPluralName())).toCharArray();
+ md.annotations = deprecate ? new Annotation[] { generateDeprecatedAnnotation(data.getSource()) } : null;
data.setGeneratedByRecursive(md);
injectMethod(builderType, md);
diff --git a/src/core/lombok/experimental/Accessors.java b/src/core/lombok/experimental/Accessors.java
index 7d9fdc5c..dc9ae4b0 100644
--- a/src/core/lombok/experimental/Accessors.java
+++ b/src/core/lombok/experimental/Accessors.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012-2013 The Project Lombok Authors.
+ * Copyright (C) 2012-2017 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
@@ -29,7 +29,7 @@ import java.lang.annotation.Target;
/**
* A container for settings for the generation of getters and setters.
* <p>
- * Complete documentation is found at <a href="https://projectlombok.org/features/experimental/Accessors.html">the project lombok features page for &#64;Accessors</a>.
+ * Complete documentation is found at <a href="https://projectlombok.org/features/experimental/Accessors">the project lombok features page for &#64;Accessors</a>.
* <p>
* Using this annotation does nothing by itself; an annotation that makes lombok generate getters and setters,
* such as {@link lombok.Setter} or {@link lombok.Data} is also required.
@@ -38,15 +38,19 @@ import java.lang.annotation.Target;
@Retention(RetentionPolicy.SOURCE)
public @interface Accessors {
/**
- * If true, accessors will be named after the field and not include a <code>get</code> or <code>set</code>
- * prefix. If true and <code>chain</code> is omitted, <code>chain</code> defaults to <code>true</code>.
+ * If true, accessors will be named after the field and not include a {@code get} or {@code set}
+ * prefix. If true and {@code chain} is omitted, {@code chain} defaults to {@code true}.
* <strong>default: false</strong>
+ *
+ * @return Whether or not to make fluent methods (named {@code fieldName()}, not for example {@code setFieldName}).
*/
boolean fluent() default false;
/**
- * If true, setters return <code>this</code> instead of <code>void</code>.
- * <strong>default: false</strong>, unless <code>fluent=true</code>, then <strong>default: true</code>
+ * If true, setters return {@code this} instead of {@code void}.
+ * <strong>default: false</strong>, unless {@code fluent=true}, then <strong>default: true</strong>
+ *
+ * @return Whether or not setters should return themselves (chaining) or {@code void} (no chaining).
*/
boolean chain() default false;
@@ -55,6 +59,8 @@ public @interface Accessors {
* Note that a prefix only counts if the next character is NOT a lowercase character or the last
* letter of the prefix is not a letter (for instance an underscore). If multiple fields
* all turn into the same name when the prefix is stripped, an error will be generated.
+ *
+ * @return If you are in the habit of prefixing your fields (for example, you name them {@code fFieldName}, specify such prefixes here).
*/
String[] prefix() default {};
}
diff --git a/src/core/lombok/experimental/Builder.java b/src/core/lombok/experimental/Builder.java
index 4d5e0f67..7b364bff 100644
--- a/src/core/lombok/experimental/Builder.java
+++ b/src/core/lombok/experimental/Builder.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013-2014 The Project Lombok Authors.
+ * Copyright (C) 2013-2017 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
@@ -48,8 +48,8 @@ import java.lang.annotation.Target;
* as the relevant class, unless a 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="https://projectlombok.org/features/experimental/Builder.html">the project lombok features page for &#64;Builder</a>.
- * <p>
+ * Complete documentation is found at <a href="https://projectlombok.org/features/Builder">the project lombok features page for &#64;Builder</a>.
+ * <br>
* <p>
* Before:
*
@@ -110,15 +110,20 @@ import java.lang.annotation.Target;
@Retention(SOURCE)
@Deprecated
public @interface Builder {
- /** Name of the method that creates a new builder instance. Default: {@code builder}. */
+ /** @return Name of the method that creates a new builder instance. Default: {@code builder}. */
String builderMethodName() default "builder";
- /** Name of the method in the builder class that creates an instance of your {@code @Builder}-annotated class. */
+ /** @return Name of the method in the builder class that creates an instance of your {@code @Builder}-annotated class. */
String buildMethodName() default "build";
- /** Name of the builder class.
+ /**
+ * Name of the builder class.
+ *
* Default for {@code @Builder} on types and constructors: {@code (TypeName)Builder}.
+ * <p>
* Default for {@code @Builder} on methods: {@code (ReturnTypeName)Builder}.
+ *
+ * @return Name of the builder class that will be generated (or if it already exists, will be filled with builder elements).
*/
String builderClassName() default "";
@@ -127,6 +132,8 @@ public @interface Builder {
* to {@code false} to name the setter method for field {@code someField}: {@code setSomeField}.
* <p>
* <strong>Default: true</strong>
+ *
+ * @return Whether to generate fluent methods (just {@code fieldName()} instead of {@code setFieldName()}).
*/
boolean fluent() default true;
@@ -135,6 +142,8 @@ public @interface Builder {
* calls to set methods. Set this to {@code false} to have these 'set' methods return {@code void} instead.
* <p>
* <strong>Default: true</strong>
+ *
+ * @return Whether to generate chaining methods (each build call returns itself instead of returning {@code void}).
*/
boolean chain() default true;
}
diff --git a/src/core/lombok/experimental/Delegate.java b/src/core/lombok/experimental/Delegate.java
index d94389b0..cc844526 100644
--- a/src/core/lombok/experimental/Delegate.java
+++ b/src/core/lombok/experimental/Delegate.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010-2014 The Project Lombok Authors.
+ * Copyright (C) 2010-2017 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
@@ -40,7 +40,7 @@ import java.lang.annotation.Target;
* that exist in {@link Object}, the {@code canEqual(Object)} method, and any methods that appear in types
* that are listed in the {@code excludes} property.
* <p>
- * Complete documentation is found at <a href="https://projectlombok.org/features/experimental/Delegate.html">the project lombok features page for &#64;Delegate</a>.
+ * Complete documentation is found at <a href="https://projectlombok.org/features/experimental/Delegate">the project lombok features page for &#64;Delegate</a>.
*/
@Target({ElementType.FIELD, ElementType.METHOD})
@Retention(RetentionPolicy.SOURCE)
@@ -52,6 +52,8 @@ public @interface Delegate {
* type listed here is used only to determine which delegate methods to generate.
*
* NB: All methods in {@code Object}, as well as {@code canEqual(Object other)} will never be delegated.
+ *
+ * @return For each method (not already in {@code java.lang.Object}) in these types, generate a delegate method.
*/
Class<?>[] types() default {};
@@ -59,6 +61,8 @@ public @interface Delegate {
* Each method in any of the types listed here (include supertypes) will <em>not</em> be delegated.
*
* NB: All methods in {@code Object}, as well as {@code canEqual(Object other)} will never be delegated.
+ *
+ * @return For each method (not already in {@code java.lang.Object}) in these types, skip generating a delegate method (overrides {@code types()}).
*/
Class<?>[] excludes() default {};
}
diff --git a/src/core/lombok/experimental/ExtensionMethod.java b/src/core/lombok/experimental/ExtensionMethod.java
index 3e64cf78..af38f6ed 100644
--- a/src/core/lombok/experimental/ExtensionMethod.java
+++ b/src/core/lombok/experimental/ExtensionMethod.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012-2013 The Project Lombok Authors.
+ * Copyright (C) 2012-2017 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
@@ -31,8 +31,8 @@ import java.lang.annotation.*;
* otherwise modifying the original type. Extension methods are a special kind of static method, but they are called as
* if they were instance methods on the extended type.
* <p>
- * Complete documentation is found at <a href="https://projectlombok.org/features/experimental/ExtensionMethod.html">the project lombok features page for &#64;ExtensionMethod</a>.
- * <p>
+ * Complete documentation is found at <a href="https://projectlombok.org/features/experimental/ExtensionMethod">the project lombok features page for &#64;ExtensionMethod</a>.
+ * <br>
* <p>
* Before:
*
@@ -60,12 +60,14 @@ import java.lang.annotation.*;
@Target(TYPE)
@Retention(SOURCE)
public @interface ExtensionMethod {
- /** All types whose static methods will be exposed as extension methods. */
+ /** @return All types whose static methods will be exposed as extension methods. */
Class<?>[] value();
/**
* If {@code true}, an applicable extension method is used (if found) even if the method call already was compilable (this is the default).
* If {@code false}, an extension method is only used if the method call is not also defined by the type itself.
+ *
+ * @return Whether or not to override already existing methods with the extension.
*/
boolean suppressBaseMethods() default true;
}
diff --git a/src/core/lombok/experimental/FieldDefaults.java b/src/core/lombok/experimental/FieldDefaults.java
index 384abda5..5c387bb6 100644
--- a/src/core/lombok/experimental/FieldDefaults.java
+++ b/src/core/lombok/experimental/FieldDefaults.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012-2013 The Project Lombok Authors.
+ * Copyright (C) 2012-2017 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
@@ -31,7 +31,7 @@ import lombok.AccessLevel;
/**
* Adds modifiers to each field in the type with this annotation.
* <p>
- * Complete documentation is found at <a href="https://projectlombok.org/features/experimental/FieldDefaults.html">the project lombok features page for &#64;FieldDefaults</a>.
+ * Complete documentation is found at <a href="https://projectlombok.org/features/experimental/FieldDefaults">the project lombok features page for &#64;FieldDefaults</a>.
* <p>
* If {@code makeFinal} is {@code true}, then each (instance) field that is not annotated with {@code @NonFinal} will have the {@code final} modifier added.
* <p>
diff --git a/src/core/lombok/experimental/Value.java b/src/core/lombok/experimental/Value.java
index 46ec7a05..06dbee13 100644
--- a/src/core/lombok/experimental/Value.java
+++ b/src/core/lombok/experimental/Value.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012-2013 The Project Lombok Authors.
+ * Copyright (C) 2012-2017 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
@@ -31,7 +31,7 @@ import java.lang.annotation.Target;
* <p>
* Equivalent to {@code @Getter @FieldDefaults(makeFinal=true, level=AccessLevel.PRIVATE) @RequiredArgsConstructor @ToString @EqualsAndHashCode}.
* <p>
- * Complete documentation is found at <a href="https://projectlombok.org/features/experimental/Value.html">the project lombok features page for &#64;Value</a>.
+ * Complete documentation is found at <a href="https://projectlombok.org/features/Value">the project lombok features page for &#64;Value</a>.
*
* @see lombok.Getter
* @see Wither
@@ -55,6 +55,8 @@ public @interface Value {
* </pre>
*
* Default: No static constructor, instead the normal constructor is public.
+ *
+ * @return Name of static 'constructor' method to generate (blank = generate a normal constructor).
*/
String staticConstructor() default "";
}
diff --git a/src/core/lombok/experimental/Wither.java b/src/core/lombok/experimental/Wither.java
index 3fb767d1..3df546d0 100644
--- a/src/core/lombok/experimental/Wither.java
+++ b/src/core/lombok/experimental/Wither.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012-2013 The Project Lombok Authors.
+ * Copyright (C) 2012-2017 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
@@ -31,7 +31,7 @@ import lombok.AccessLevel;
/**
* Put on any field to make lombok build a 'wither' - a withX method which produces a clone of this object (except for 1 field which gets a new value).
* <p>
- * Complete documentation is found at <a href="https://projectlombok.org/features/experimental/Wither.html">the project lombok features page for &#64;Wither</a>.
+ * Complete documentation is found at <a href="https://projectlombok.org/features/experimental/Wither">the project lombok features page for &#64;Wither</a>.
* <p>
* Even though it is not listed, this annotation also has the {@code onParam} and {@code onMethod} parameter. See the full documentation for more details.
* <p>
@@ -56,26 +56,32 @@ import lombok.AccessLevel;
public @interface Wither {
/**
* If you want your wither to be non-public, you can specify an alternate access level here.
+ *
+ * @return The method will be generated with this access modifier.
*/
AccessLevel value() default AccessLevel.PUBLIC;
/**
* Any annotations listed here are put on the generated method.
- * The syntax for this feature depends on JDK version (nothing we can do about that; it's to work around javac bugs).<br />
- * up to JDK7:<br />
- * {@code @Wither(onMethod=@__({@AnnotationsGoHere}))}<br />
- * from JDK8:<br />
+ * The syntax for this feature depends on JDK version (nothing we can do about that; it's to work around javac bugs).<br>
+ * up to JDK7:<br>
+ * {@code @Wither(onMethod=@__({@AnnotationsGoHere}))}<br>
+ * from JDK8:<br>
* {@code @Wither(onMethod_={@AnnotationsGohere})} // note the underscore after {@code onMethod}.
+ *
+ * @return List of annotations to apply to the generated method.
*/
AnyAnnotation[] onMethod() default {};
/**
* Any annotations listed here are put on the generated method's parameter.
- * The syntax for this feature depends on JDK version (nothing we can do about that; it's to work around javac bugs).<br />
- * up to JDK7:<br />
- * {@code @Wither(onParam=@__({@AnnotationsGoHere}))}<br />
- * from JDK8:<br />
+ * The syntax for this feature depends on JDK version (nothing we can do about that; it's to work around javac bugs).<br>
+ * up to JDK7:<br>
+ * {@code @Wither(onParam=@__({@AnnotationsGoHere}))}<br>
+ * from JDK8:<br>
* {@code @Wither(onParam_={@AnnotationsGohere})} // note the underscore after {@code onParam}.
+ *
+ * @return List of annotations to apply to the generated parameter in the method.
*/
AnyAnnotation[] onParam() default {};
diff --git a/src/core/lombok/experimental/package-info.java b/src/core/lombok/experimental/package-info.java
index d85e2969..22b23a52 100644
--- a/src/core/lombok/experimental/package-info.java
+++ b/src/core/lombok/experimental/package-info.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009-2014 The Project Lombok Authors.
+ * Copyright (C) 2009-2017 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
@@ -28,6 +28,6 @@
* to the official feature documentation.
*
* @see lombok
- * @see <a href="https://projectlombok.org/features/experimental/index.html">Lombok features (experimental)</a>
+ * @see <a href="https://projectlombok.org/features/experimental/all">Lombok features (experimental)</a>
*/
package lombok.experimental;
diff --git a/src/core/lombok/extern/apachecommons/CommonsLog.java b/src/core/lombok/extern/apachecommons/CommonsLog.java
index 777f4b35..04d5ef93 100644
--- a/src/core/lombok/extern/apachecommons/CommonsLog.java
+++ b/src/core/lombok/extern/apachecommons/CommonsLog.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010-2013 The Project Lombok Authors.
+ * Copyright (C) 2010-2017 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
@@ -29,7 +29,7 @@ import java.lang.annotation.Target;
/**
* Causes lombok to generate a logger field.
* <p>
- * Complete documentation is found at <a href="https://projectlombok.org/features/Log.html">the project lombok features page for lombok log annotations</a>.
+ * Complete documentation is found at <a href="https://projectlombok.org/features/Log">the project lombok features page for lombok log annotations</a>.
* <p>
* Example:
* <pre>
@@ -46,10 +46,10 @@ import java.lang.annotation.Target;
* }
* </pre>
*
- * This annotation is valid for classes and enumerations.<br />
+ * This annotation is valid for classes and enumerations.<br>
*
- * @see org.apache.commons.logging.Log org.apache.commons.logging.Log
- * @see org.apache.commons.logging.LogFactory#getLog(java.lang.Class) org.apache.commons.logging.LogFactory.getLog(Class target)
+ * @see <a href="https://commons.apache.org/proper/commons-logging/apidocs/org/apache/commons/logging/Log.html">org.apache.commons.logging.Log</a>
+ * @see <a href="https://commons.apache.org/proper/commons-logging/apidocs/org/apache/commons/logging/LogFactory.html#getLog(java.lang.Class)">org.apache.commons.logging.LogFactory#getLog(java.lang.Class)</a>
* @see lombok.extern.java.Log &#64;Log
* @see lombok.extern.log4j.Log4j &#64;Log4j
* @see lombok.extern.log4j.Log4j2 &#64;Log4j2
@@ -60,8 +60,6 @@ import java.lang.annotation.Target;
@Retention(RetentionPolicy.SOURCE)
@Target(ElementType.TYPE)
public @interface CommonsLog {
- /**
- * Sets the category of the constructed Logger. By default, it will use the type where the annotation is placed.
- */
+ /** @return The category of the constructed Logger. By default, it will use the type where the annotation is placed. */
String topic() default "";
}
diff --git a/src/core/lombok/extern/java/Log.java b/src/core/lombok/extern/java/Log.java
index d5515283..553b7c4a 100644
--- a/src/core/lombok/extern/java/Log.java
+++ b/src/core/lombok/extern/java/Log.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010-2013 The Project Lombok Authors.
+ * Copyright (C) 2010-2017 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
@@ -29,7 +29,7 @@ import java.lang.annotation.Target;
/**
* Causes lombok to generate a logger field.
* <p>
- * Complete documentation is found at <a href="https://projectlombok.org/features/Log.html">the project lombok features page for lombok log annotations</a>.
+ * Complete documentation is found at <a href="https://projectlombok.org/features/Log">the project lombok features page for lombok log annotations</a>.
* <p>
* Example:
* <pre>
@@ -46,9 +46,9 @@ import java.lang.annotation.Target;
* }
* </pre>
*
- * This annotation is valid for classes and enumerations.<br />
- * @see java.util.logging.Logger java.util.logging.Logger
- * @see java.util.logging.Logger#getLogger(java.lang.String) java.util.logging.Logger.getLogger(String name)
+ * This annotation is valid for classes and enumerations.<br>
+ * @see <a href="https://docs.oracle.com/javase/8/docs/api/java/util/logging/Logger.html">java.util.logging.Logger</a>
+ * @see <a href="https://docs.oracle.com/javase/8/docs/api/java/util/logging/Logger.html#getLogger-java.lang.String-">java.util.logging.Logger#getLogger(java.lang.String)</a>
* @see lombok.extern.apachecommons.CommonsLog &#64;CommonsLog
* @see lombok.extern.log4j.Log4j &#64;Log4j
* @see lombok.extern.log4j.Log4j2 &#64;Log4j2
@@ -59,8 +59,6 @@ import java.lang.annotation.Target;
@Retention(RetentionPolicy.SOURCE)
@Target(ElementType.TYPE)
public @interface Log {
- /**
- * Sets the category of the constructed Logger. By default, it will use the type where the annotation is placed.
- */
+ /** @return The category of the constructed Logger. By default, it will use the type where the annotation is placed. */
String topic() default "";
}
diff --git a/src/core/lombok/extern/jbosslog/JBossLog.java b/src/core/lombok/extern/jbosslog/JBossLog.java
index 2735290c..ea520aea 100644
--- a/src/core/lombok/extern/jbosslog/JBossLog.java
+++ b/src/core/lombok/extern/jbosslog/JBossLog.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2016 The Project Lombok Authors.
+ * Copyright (C) 2016-2017 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
@@ -29,7 +29,7 @@ import java.lang.annotation.Target;
/**
* Causes lombok to generate a logger field.
* <p>
- * Complete documentation is found at <a href="https://projectlombok.org/features/Log.html">the project lombok features page for lombok log annotations</a>.
+ * Complete documentation is found at <a href="https://projectlombok.org/features/Log">the project lombok features page for lombok log annotations</a>.
* <p>
* Example:
* <pre>
@@ -46,9 +46,9 @@ import java.lang.annotation.Target;
* }
* </pre>
*
- * This annotation is valid for classes and enumerations.<br />
- * @see org.jboss.logging.Logger org.jboss.logging.Logger
- * @see org.jboss.logging.Logger#getLogger(java.lang.Class) org.jboss.logging.Logger.getLogger(Class target)
+ * This annotation is valid for classes and enumerations.<br>
+ * @see <a href="https://docs.jboss.org/jbosslogging/latest/org/jboss/logging/Logger.html">org.jboss.logging.Logger</a>
+ * @see <a href="https://docs.jboss.org/jbosslogging/latest/org/jboss/logging/Logger.html#getLogger(java.lang.Class)">org.jboss.logging.Logger#getLogger(java.lang.Class)</a>
* @see lombok.extern.apachecommons.CommonsLog &#64;CommonsLog
* @see lombok.extern.java.Log &#64;Log
* @see lombok.extern.log4j.Log4j &#64;Log4j
@@ -59,9 +59,6 @@ import java.lang.annotation.Target;
@Retention(RetentionPolicy.SOURCE)
@Target(ElementType.TYPE)
public @interface JBossLog {
-
- /**
- * Sets the category of the constructed Logger. By default, it will use the type where the annotation is placed.
- */
+ /** @return The category of the constructed Logger. By default, it will use the type where the annotation is placed. */
String topic() default "";
}
diff --git a/src/core/lombok/extern/log4j/Log4j.java b/src/core/lombok/extern/log4j/Log4j.java
index 6c6ef1da..ee719407 100644
--- a/src/core/lombok/extern/log4j/Log4j.java
+++ b/src/core/lombok/extern/log4j/Log4j.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010-2013 The Project Lombok Authors.
+ * Copyright (C) 2010-2017 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
@@ -29,7 +29,7 @@ import java.lang.annotation.Target;
/**
* Causes lombok to generate a logger field.
* <p>
- * Complete documentation is found at <a href="https://projectlombok.org/features/Log.html">the project lombok features page for lombok log annotations</a>.
+ * Complete documentation is found at <a href="https://projectlombok.org/features/Log">the project lombok features page for lombok log annotations</a>.
* <p>
* Example:
* <pre>
@@ -46,10 +46,10 @@ import java.lang.annotation.Target;
* }
* </pre>
*
- * This annotation is valid for classes and enumerations.<br />
+ * This annotation is valid for classes and enumerations.<br>
*
- * @see org.apache.log4j.Logger org.apache.log4j.Logger
- * @see org.apache.log4j.Logger#getLogger(java.lang.Class) org.apache.log4j.Logger.getLogger(Class target)
+ * @see <a href="https://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/Logger.html">org.apache.log4j.Logger</a>
+ * @see <a href="https://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/Logger.html#getLogger(java.lang.Class)">org.apache.log4j.Logger#getLogger(java.lang.Class)</a>
* @see lombok.extern.log4j.Log4j2 &#64;Log4j2
* @see lombok.extern.apachecommons.CommonsLog &#64;CommonsLog
* @see lombok.extern.java.Log &#64;Log
@@ -60,8 +60,6 @@ import java.lang.annotation.Target;
@Retention(RetentionPolicy.SOURCE)
@Target(ElementType.TYPE)
public @interface Log4j {
- /**
- * Sets the category of the constructed Logger. By default, it will use the type where the annotation is placed.
- */
+ /** @return The category of the constructed Logger. By default, it will use the type where the annotation is placed. */
String topic() default "";
}
diff --git a/src/core/lombok/extern/log4j/Log4j2.java b/src/core/lombok/extern/log4j/Log4j2.java
index a1b2e0e7..4a5b166c 100644
--- a/src/core/lombok/extern/log4j/Log4j2.java
+++ b/src/core/lombok/extern/log4j/Log4j2.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013 The Project Lombok Authors.
+ * Copyright (C) 2013-2017 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
@@ -29,7 +29,7 @@ import java.lang.annotation.Target;
/**
* Causes lombok to generate a logger field.
* <p>
- * Complete documentation is found at <a href="https://projectlombok.org/features/Log.html">the project lombok features page for lombok log annotations</a>.
+ * Complete documentation is found at <a href="https://projectlombok.org/features/Log">the project lombok features page for lombok log annotations</a>.
* <p>
* Example:
* <pre>
@@ -46,10 +46,10 @@ import java.lang.annotation.Target;
* }
* </pre>
*
- * This annotation is valid for classes and enumerations.<br />
+ * This annotation is valid for classes and enumerations.<br>
*
- * @see org.apache.logging.log4j.Logger org.apache.logging.log4j.Logger
- * @see org.apache.logging.log4j.LogManager#getLogger(java.lang.Class) org.apache.logging.log4j.LogManager.getLogger(Class target)
+ * @see <a href="https://logging.apache.org/log4j/2.x/log4j-api/apidocs/org/apache/logging/log4j/Logger.html">org.apache.logging.log4j.Logger</a>
+ * @see <a href="https://logging.apache.org/log4j/2.x/log4j-api/apidocs/org/apache/logging/log4j/LogManager.html#getLogger-java.lang.Class-">org.apache.logging.log4j.LogManager#getLogger(java.lang.Class)</a>
* @see lombok.extern.log4j.Log4j &#64;Log4j
* @see lombok.extern.apachecommons.CommonsLog &#64;CommonsLog
* @see lombok.extern.java.Log &#64;Log
@@ -60,8 +60,6 @@ import java.lang.annotation.Target;
@Retention(RetentionPolicy.SOURCE)
@Target(ElementType.TYPE)
public @interface Log4j2 {
- /**
- * Sets the category of the constructed Logger. By default, it will use the type where the annotation is placed.
- */
+ /** @return The category of the constructed Logger. By default, it will use the type where the annotation is placed. */
String topic() default "";
}
diff --git a/src/core/lombok/extern/slf4j/Slf4j.java b/src/core/lombok/extern/slf4j/Slf4j.java
index efa6105f..24586d43 100644
--- a/src/core/lombok/extern/slf4j/Slf4j.java
+++ b/src/core/lombok/extern/slf4j/Slf4j.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010-2013 The Project Lombok Authors.
+ * Copyright (C) 2010-2017 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
@@ -29,7 +29,7 @@ import java.lang.annotation.Target;
/**
* Causes lombok to generate a logger field.
* <p>
- * Complete documentation is found at <a href="https://projectlombok.org/features/Log.html">the project lombok features page for lombok log annotations</a>.
+ * Complete documentation is found at <a href="https://projectlombok.org/features/Log">the project lombok features page for lombok log annotations</a>.
* <p>
* Example:
* <pre>
@@ -46,9 +46,9 @@ import java.lang.annotation.Target;
* }
* </pre>
*
- * This annotation is valid for classes and enumerations.<br />
- * @see org.slf4j.Logger org.slf4j.Logger
- * @see org.slf4j.LoggerFactory#getLogger(java.lang.Class) org.slf4j.LoggerFactory.getLogger(Class target)
+ * This annotation is valid for classes and enumerations.<br>
+ * @see <a href="https://www.slf4j.org/api/org/slf4j/Logger.html">org.slf4j.Logger</a>
+ * @see <a href="https://www.slf4j.org/api/org/slf4j/LoggerFactory.html#getLogger(java.lang.Class)">org.slf4j.LoggerFactory#getLogger(java.lang.Class)</a>
* @see lombok.extern.apachecommons.CommonsLog &#64;CommonsLog
* @see lombok.extern.java.Log &#64;Log
* @see lombok.extern.log4j.Log4j &#64;Log4j
@@ -59,9 +59,7 @@ import java.lang.annotation.Target;
@Retention(RetentionPolicy.SOURCE)
@Target(ElementType.TYPE)
public @interface Slf4j {
- /**
- * Sets the category of the constructed Logger. By default, it will use the type where the annotation is placed.
- */
+ /** @return The category of the constructed Logger. By default, it will use the type where the annotation is placed. */
String topic() default "";
}
diff --git a/src/core/lombok/extern/slf4j/XSlf4j.java b/src/core/lombok/extern/slf4j/XSlf4j.java
index ce23ab9e..85a0fdd8 100644
--- a/src/core/lombok/extern/slf4j/XSlf4j.java
+++ b/src/core/lombok/extern/slf4j/XSlf4j.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012-2013 The Project Lombok Authors.
+ * Copyright (C) 2012-2017 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
@@ -29,7 +29,7 @@ import java.lang.annotation.Target;
/**
* Causes lombok to generate a logger field.
* <p>
- * Complete documentation is found at <a href="https://projectlombok.org/features/Log.html">the project lombok features page for lombok log annotations</a>.
+ * Complete documentation is found at <a href="https://projectlombok.org/features/Log">the project lombok features page for lombok log annotations</a>.
* <p>
* Example:
* <pre>
@@ -46,9 +46,9 @@ import java.lang.annotation.Target;
* }
* </pre>
*
- * This annotation is valid for classes and enumerations.<br />
- * @see org.slf4j.ext.XLogger org.slf4j.ext.XLogger
- * @see org.slf4j.ext.XLoggerFactory#getLogger(java.lang.Class) org.slf4j.ext.XLoggerFactory.getXLogger(Class target)
+ * This annotation is valid for classes and enumerations.<br>
+ * @see <a href="https://www.slf4j.org/api/org/slf4j/ext/XLogger.html">org.slf4j.ext.XLogger</a>
+ * @see <a href="https://www.slf4j.org/api/org/slf4j/ext/XLoggerFactory.html#getXLogger(java.lang.Class)">org.slf4j.ext.XLoggerFactory#getLogger(java.lang.Class)</a>
* @see lombok.extern.apachecommons.CommonsLog &#64;CommonsLog
* @see lombok.extern.java.Log &#64;Log
* @see lombok.extern.log4j.Log4j &#64;Log4j
@@ -59,8 +59,6 @@ import java.lang.annotation.Target;
@Retention(RetentionPolicy.SOURCE)
@Target(ElementType.TYPE)
public @interface XSlf4j {
- /**
- * Sets the category of the constructed Logger. By default, it will use the type where the annotation is placed.
- */
+ /** @return The category of the constructed Logger. By default, it will use the type where the annotation is placed. */
String topic() default "";
}
diff --git a/src/core/lombok/javac/CompilerMessageSuppressor.java b/src/core/lombok/javac/CompilerMessageSuppressor.java
index a17e0c62..391ec64a 100644
--- a/src/core/lombok/javac/CompilerMessageSuppressor.java
+++ b/src/core/lombok/javac/CompilerMessageSuppressor.java
@@ -26,6 +26,7 @@ import java.io.OutputStream;
import java.io.PrintWriter;
import java.lang.reflect.Field;
import java.util.LinkedList;
+import java.util.Map;
import java.util.Queue;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
@@ -43,38 +44,40 @@ import com.sun.tools.javac.util.Log;
* then they will be generated AGAIN, this time with proper names and line numbers, at the end. Therefore, we want to suppress the logger.
*/
public final class CompilerMessageSuppressor {
+
private final Log log;
- private static final Field errWriterField, warnWriterField, noticeWriterField, dumpOnErrorField, promptOnErrorField, diagnosticListenerField;
+ private static final WriterField errWriterField, warnWriterField, noticeWriterField;
+ private static final Field dumpOnErrorField, promptOnErrorField, diagnosticListenerField;
private static final Field deferDiagnosticsField, deferredDiagnosticsField, diagnosticHandlerField;
private static final ConcurrentMap<Class<?>, Field> handlerDeferredFields = new ConcurrentHashMap<Class<?>, Field>();
private static final Field NULL_FIELD;
- private PrintWriter errWriter, warnWriter, noticeWriter;
private Boolean dumpOnError, promptOnError;
private DiagnosticListener<?> contextDiagnosticListener, logDiagnosticListener;
private final Context context;
- // If this is true, the fields changed. Better to print weird error messages than to fail outright.
- private static final boolean dontBother;
-
private static final ThreadLocal<Queue<?>> queueCache = new ThreadLocal<Queue<?>>();
+ enum Writers {
+ ERROR("errWriter", "ERROR"),
+ WARNING("warnWriter", "WARNING"),
+ NOTICE("noticeWriter", "NOTICE");
+
+ final String fieldName;
+ final String keyName;
+
+ Writers(String fieldName, String keyName) {
+ this.fieldName = fieldName;
+ this.keyName = keyName;
+ }
+ }
+
static {
- errWriterField = getDeclaredField(Log.class, "errWriter");
- warnWriterField = getDeclaredField(Log.class, "warnWriter");
- noticeWriterField = getDeclaredField(Log.class, "noticeWriter");
+ errWriterField = createWriterField(Writers.ERROR);
+ warnWriterField = createWriterField(Writers.WARNING);
+ noticeWriterField = createWriterField(Writers.NOTICE);
dumpOnErrorField = getDeclaredField(Log.class, "dumpOnError");
promptOnErrorField = getDeclaredField(Log.class, "promptOnError");
diagnosticListenerField = getDeclaredField(Log.class, "diagListener");
-
- dontBother =
- errWriterField == null ||
- warnWriterField == null ||
- noticeWriterField == null ||
- dumpOnErrorField == null ||
- promptOnErrorField == null ||
- diagnosticListenerField == null;
-
-
deferDiagnosticsField = getDeclaredField(Log.class, "deferDiagnostics");
deferredDiagnosticsField = getDeclaredField(Log.class, "deferredDiagnostics");
@@ -100,17 +103,13 @@ public final class CompilerMessageSuppressor {
this.context = context;
}
- public boolean disableLoggers() {
+ public void disableLoggers() {
contextDiagnosticListener = context.get(DiagnosticListener.class);
context.put(DiagnosticListener.class, (DiagnosticListener<?>) null);
- if (dontBother) return false;
- boolean dontBotherInstance = false;
-
- PrintWriter dummyWriter = new PrintWriter(new OutputStream() {
- @Override public void write(int b) throws IOException {
- // Do nothing on purpose
- }
- });
+
+ errWriterField.pauze(log);
+ warnWriterField.pauze(log);
+ noticeWriterField.pauze(log);
if (deferDiagnosticsField != null) try {
if (Boolean.TRUE.equals(deferDiagnosticsField.get(log))) {
@@ -130,50 +129,23 @@ public final class CompilerMessageSuppressor {
}
} catch (Exception e) {}
- if (!dontBotherInstance) try {
- errWriter = (PrintWriter) errWriterField.get(log);
- errWriterField.set(log, dummyWriter);
- } catch (Exception e) {
- dontBotherInstance = true;
- }
-
- if (!dontBotherInstance) try {
- warnWriter = (PrintWriter) warnWriterField.get(log);
- warnWriterField.set(log, dummyWriter);
- } catch (Exception e) {
- dontBotherInstance = true;
- }
-
- if (!dontBotherInstance) try {
- noticeWriter = (PrintWriter) noticeWriterField.get(log);
- noticeWriterField.set(log, dummyWriter);
- } catch (Exception e) {
- dontBotherInstance = true;
- }
-
- if (!dontBotherInstance) try {
+ if (dumpOnErrorField != null) try {
dumpOnError = (Boolean) dumpOnErrorField.get(log);
dumpOnErrorField.set(log, false);
} catch (Exception e) {
- dontBotherInstance = true;
}
- if (!dontBotherInstance) try {
+ if (promptOnErrorField != null) try {
promptOnError = (Boolean) promptOnErrorField.get(log);
promptOnErrorField.set(log, false);
} catch (Exception e) {
- dontBotherInstance = true;
}
- if (!dontBotherInstance) try {
+ if (diagnosticListenerField != null) try {
logDiagnosticListener = (DiagnosticListener<?>) diagnosticListenerField.get(log);
diagnosticListenerField.set(log, null);
} catch (Exception e) {
- dontBotherInstance = true;
}
-
- if (dontBotherInstance) enableLoggers();
- return !dontBotherInstance;
}
private static Field getDeferredField(Object handler) {
@@ -193,20 +165,9 @@ public final class CompilerMessageSuppressor {
contextDiagnosticListener = null;
}
- if (errWriter != null) try {
- errWriterField.set(log, errWriter);
- errWriter = null;
- } catch (Exception e) {}
-
- if (warnWriter != null) try {
- warnWriterField.set(log, warnWriter);
- warnWriter = null;
- } catch (Exception e) {}
-
- if (noticeWriter != null) try {
- noticeWriterField.set(log, noticeWriter);
- noticeWriter = null;
- } catch (Exception e) {}
+ errWriterField.resume(log);
+ warnWriterField.resume(log);
+ noticeWriterField.resume(log);
if (dumpOnError != null) try {
dumpOnErrorField.set(log, dumpOnError);
@@ -283,4 +244,107 @@ public final class CompilerMessageSuppressor {
// javac will contain rather a lot of messages, but this is a lot better than just crashing during compilation!
}
}
+
+ private static WriterField createWriterField(Writers w) {
+ // jdk9
+ try {
+ Field writers = getDeclaredField(Log.class, "writer");
+ if (writers != null) {
+ Class<?> kindsClass = Class.forName("com.sun.tools.javac.util.Log$WriterKind");
+ for (Object enumConstant : kindsClass.getEnumConstants()) {
+ if (enumConstant.toString().equals(w.keyName)) {
+ return new Java9WriterField(writers, enumConstant);
+ }
+ }
+ return WriterField.NONE;
+ }
+ } catch (Exception e) {
+ }
+
+ // jdk8
+ Field writerField = getDeclaredField(Log.class, w.fieldName);
+ if (writerField != null) return new Java8WriterField(writerField);
+
+ // other jdk
+ return WriterField.NONE;
+ }
+
+ interface WriterField {
+ final PrintWriter NO_WRITER = new PrintWriter(new OutputStream() {
+ @Override public void write(int b) throws IOException {
+ // Do nothing on purpose
+ }
+ });
+
+ final WriterField NONE = new WriterField() {
+ @Override public void pauze(Log log) {
+ // do nothing
+ }
+ @Override public void resume(Log log) {
+ // no nothing
+ }
+ };
+
+ void pauze(Log log);
+ void resume(Log log);
+ }
+
+ static class Java8WriterField implements WriterField {
+ private final Field field;
+ private PrintWriter writer;
+
+ public Java8WriterField(Field field) {
+ this.field = field;
+ }
+
+ @Override public void pauze(Log log) {
+ try {
+ writer = (PrintWriter) field.get(log);
+ field.set(log, NO_WRITER);
+ } catch (Exception e) {
+ }
+ }
+
+ @Override public void resume(Log log) {
+ if (writer != null) {
+ try {
+ field.set(log, writer);
+ } catch (Exception e) {
+ }
+ }
+ writer = null;
+ }
+ }
+
+
+ static class Java9WriterField implements WriterField {
+ private final Field field;
+ private final Object key;
+ private PrintWriter writer;
+
+ public Java9WriterField(Field field, Object key) {
+ this.field = field;
+ this.key = key;
+ }
+
+ @Override public void pauze(Log log) {
+ try {
+ @SuppressWarnings("unchecked") Map<Object,PrintWriter> map = (Map<Object,PrintWriter>)field.get(log);
+ writer = map.get(key);
+ map.put(key, NO_WRITER);
+ } catch (Exception e) {
+ }
+ }
+
+ @Override public void resume(Log log) {
+ if (writer != null) {
+ try {
+ @SuppressWarnings("unchecked") Map<Object,PrintWriter> map = (Map<Object,PrintWriter>)field.get(log);
+ map.put(key, writer);
+ } catch (Exception e) {
+ }
+ }
+ writer = null;
+ }
+ }
} \ No newline at end of file
diff --git a/src/core/lombok/javac/JavacAST.java b/src/core/lombok/javac/JavacAST.java
index c99ae5c9..91ed325f 100644
--- a/src/core/lombok/javac/JavacAST.java
+++ b/src/core/lombok/javac/JavacAST.java
@@ -65,12 +65,12 @@ import com.sun.tools.javac.util.Name;
* something javac's own AST system does not offer.
*/
public class JavacAST extends AST<JavacAST, JavacNode, JCTree> {
- private final Messager messager;
private final JavacElements elements;
private final JavacTreeMaker treeMaker;
private final Symtab symtab;
private final JavacTypes javacTypes;
private final Log log;
+ private final ErrorLog errorLogger;
private final Context context;
/**
@@ -84,8 +84,8 @@ public class JavacAST extends AST<JavacAST, JavacNode, JCTree> {
super(sourceName(top), PackageName.getPackageName(top), new JavacImportList(top), statementTypes());
setTop(buildCompilationUnit(top));
this.context = context;
- this.messager = messager;
this.log = Log.instance(context);
+ this.errorLogger = ErrorLog.create(messager, log);
this.elements = JavacElements.instance(context);
this.treeMaker = new JavacTreeMaker(TreeMaker.instance(context));
this.symtab = Symtab.instance(context);
@@ -422,22 +422,21 @@ public class JavacAST extends AST<JavacAST, JavacNode, JCTree> {
try {
switch (kind) {
case ERROR:
- increaseErrorCount(messager);
- boolean prev = log.multipleErrors;
- log.multipleErrors = true;
- try {
- log.error(pos, "proc.messager", message);
- } finally {
- log.multipleErrors = prev;
- }
+ errorLogger.error(pos, message);
+ break;
+ case MANDATORY_WARNING:
+ errorLogger.mandatoryWarning(pos, message);
break;
- default:
case WARNING:
- log.warning(pos, "proc.messager", message);
+ errorLogger.warning(pos, message);
+ break;
+ default:
+ case NOTE:
+ errorLogger.note(pos, message);
break;
}
} finally {
- if (oldSource != null) log.useSource(oldSource);
+ if (newSource != null) log.useSource(oldSource);
}
}
@@ -475,16 +474,118 @@ public class JavacAST extends AST<JavacAST, JavacNode, JCTree> {
return oldL;
}
- private void increaseErrorCount(Messager m) {
- try {
- Field f = m.getClass().getDeclaredField("errorCount");
- f.setAccessible(true);
- if (f.getType() == int.class) {
- int val = ((Number)f.get(m)).intValue();
- f.set(m, val +1);
+ abstract static class ErrorLog {
+ final Log log;
+ private final Messager messager;
+ private final Field errorCount;
+ private final Field warningCount;
+
+ private ErrorLog(Log log, Messager messager, Field errorCount, Field warningCount) {
+ this.log = log;
+ this.messager = messager;
+ this.errorCount = errorCount;
+ this.warningCount = warningCount;
+ }
+
+ final void error(DiagnosticPosition pos, String message) {
+ increment(errorCount);
+ error1(pos, message);
+ }
+
+ final void warning(DiagnosticPosition pos, String message) {
+ increment(warningCount);
+ log.warning(pos, "proc.messager", message);
+ }
+
+ final void mandatoryWarning(DiagnosticPosition pos, String message) {
+ increment(warningCount);
+ log.mandatoryWarning(pos, "proc.messager", message);
+ }
+
+ final void note(DiagnosticPosition pos, String message) {
+ log.note(pos, "proc.messager", message);
+ }
+
+ abstract void error1(DiagnosticPosition pos, String message);
+
+ private void increment(Field field) {
+ if (field == null) return;
+ try {
+ int val = ((Number)field.get(messager)).intValue();
+ field.set(messager, val +1);
+ } catch (Throwable t) {
+ //Very unfortunate, but in most cases it still works fine, so we'll silently swallow it.
}
- } catch (Throwable t) {
- //Very unfortunate, but in most cases it still works fine, so we'll silently swallow it.
+ }
+
+ static ErrorLog create(Messager messager, Log log) {
+ Field errorCount = null;
+ try {
+ Field f = messager.getClass().getDeclaredField("errorCount");
+ f.setAccessible(true);
+ errorCount = f;
+ } catch (Throwable t) {}
+ boolean hasMultipleErrors = false;
+ for (Field field : log.getClass().getFields()) {
+ if (field.getName().equals("multipleErrors")) {
+ hasMultipleErrors = true;
+ break;
+ }
+ }
+ if (hasMultipleErrors) return new JdkBefore9(log, messager, errorCount);
+
+ Field warningCount = null;
+ try {
+ Field f = messager.getClass().getDeclaredField("warningCount");
+ f.setAccessible(true);
+ warningCount = f;
+ } catch (Throwable t) {}
+
+
+ Method logMethod = null;
+ Object multiple = null;
+ try {
+ Class<?> df = Class.forName("com.sun.tools.javac.util.JCDiagnostic$DiagnosticFlag");
+ for (Object constant : df.getEnumConstants()) {
+ if (constant.toString().equals("MULTIPLE")) multiple = constant;
+ }
+ logMethod = log.getClass().getMethod("error", new Class<?>[] {df, DiagnosticPosition.class, String.class, Object[].class});
+ } catch (Throwable t) {}
+
+ return new Jdk9Plus(log, messager, errorCount, warningCount, logMethod, multiple);
+ }
+ }
+
+ static class JdkBefore9 extends ErrorLog {
+ private JdkBefore9(Log log, Messager messager, Field errorCount) {
+ super(log, messager, errorCount, null);
+ }
+
+ @Override void error1(DiagnosticPosition pos, String message) {
+ boolean prev = log.multipleErrors;
+ log.multipleErrors = true;
+ try {
+ log.error(pos, "proc.messager", message);
+ } finally {
+ log.multipleErrors = prev;
+ }
+ }
+ }
+
+ static class Jdk9Plus extends ErrorLog {
+ private final Object multiple;
+ private final Method logMethod;
+
+ private Jdk9Plus(Log log, Messager messager, Field errorCount, Field warningCount, Method logMethod, Object multiple) {
+ super(log, messager, errorCount, warningCount);
+ this.logMethod = logMethod;
+ this.multiple = multiple;
+ }
+
+ @Override void error1(DiagnosticPosition pos, String message) {
+ try {
+ logMethod.invoke(multiple, pos, "proc.messager", message);
+ } catch (Throwable t) {}
}
}
}
diff --git a/src/core/lombok/javac/apt/LombokFileObjects.java b/src/core/lombok/javac/apt/LombokFileObjects.java
index 7e818cab..cb2036e9 100644
--- a/src/core/lombok/javac/apt/LombokFileObjects.java
+++ b/src/core/lombok/javac/apt/LombokFileObjects.java
@@ -22,8 +22,10 @@
package lombok.javac.apt;
+import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.net.URI;
+import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.concurrent.atomic.AtomicBoolean;
@@ -31,10 +33,10 @@ import javax.tools.JavaFileManager;
import javax.tools.JavaFileObject;
import javax.tools.JavaFileObject.Kind;
-import com.sun.tools.javac.file.BaseFileManager;
-
import lombok.core.DiagnosticsReceiver;
+import com.sun.tools.javac.file.BaseFileManager;
+
//Can't use SimpleJavaFileObject so we copy/paste most of its content here, because javac doesn't follow the interface,
//and casts to its own BaseFileObject type. D'oh!
final class LombokFileObjects {
@@ -98,7 +100,9 @@ final class LombokFileObjects {
String jfmClassName = jfm != null ? jfm.getClass().getName() : "null";
if (jfmClassName.equals("com.sun.tools.javac.util.DefaultFileManager")) return Compiler.JAVAC6;
if (jfmClassName.equals("com.sun.tools.javac.util.JavacFileManager")) return Compiler.JAVAC6;
- if (jfmClassName.equals("com.sun.tools.javac.file.JavacFileManager")) {
+ if (jfmClassName.equals("com.sun.tools.javac.file.JavacFileManager") ||
+ jfmClassName.equals("com.google.errorprone.MaskedClassLoader$MaskedFileManager") ||
+ jfmClassName.equals("com.google.devtools.build.buildjar.javac.BlazeJavacMain$ClassloaderMaskingFileManager")) {
try {
Class<?> superType = Class.forName("com.sun.tools.javac.file.BaseFileManager");
if (superType.isInstance(jfm)) {
@@ -108,6 +112,18 @@ final class LombokFileObjects {
catch (Exception e) {}
return Compiler.JAVAC7;
}
+ if (jfmClassName.equals("com.sun.tools.javac.api.ClientCodeWrapper$WrappedStandardJavaFileManager")) {
+ try {
+ Field wrappedField = Class.forName("com.sun.tools.javac.api.ClientCodeWrapper$WrappedJavaFileManager").getDeclaredField("clientJavaFileManager");
+ wrappedField.setAccessible(true);
+ JavaFileManager wrappedManager = (JavaFileManager)wrappedField.get(jfm);
+ Class<?> superType = Class.forName("com.sun.tools.javac.file.BaseFileManager");
+ if (superType.isInstance(wrappedManager)) {
+ return new Java9Compiler(wrappedManager);
+ }
+ }
+ catch (Exception e) {}
+ }
try {
if (Class.forName("com.sun.tools.javac.file.BaseFileObject") == null) throw new NullPointerException();
return Compiler.JAVAC7;
@@ -116,7 +132,15 @@ final class LombokFileObjects {
if (Class.forName("com.sun.tools.javac.util.BaseFileObject") == null) throw new NullPointerException();
return Compiler.JAVAC6;
} catch (Exception e) {}
- return null;
+
+ StringBuilder sb = new StringBuilder(jfmClassName);
+ if (jfm != null) {
+ sb.append(" extends ").append(jfm.getClass().getSuperclass().getName());
+ for (Class<?> cls : jfm.getClass().getInterfaces()) {
+ sb.append(" implements ").append(cls.getName());
+ }
+ }
+ throw new IllegalArgumentException(sb.toString());
}
static JavaFileObject createEmpty(Compiler compiler, String name, Kind kind) {
@@ -137,9 +161,15 @@ final class LombokFileObjects {
@Override public JavaFileObject wrap(LombokFileObject fileObject) {
URI uri = fileObject.toUri();
if (uri.getScheme() == null) {
- uri = URI.create("file://" + uri);
+ uri = URI.create("file:///" + uri);
+ }
+ Path path;
+ try {
+ path = Paths.get(uri);
+ } catch (IllegalArgumentException e) {
+ throw new IllegalArgumentException("Problems in URI '" + uri + "' (" + fileObject.toUri() + ")", e);
}
- return new Javac9BaseFileObjectWrapper(fileManager, Paths.get(uri), fileObject);
+ return new Javac9BaseFileObjectWrapper(fileManager, path, fileObject);
}
@Override public Method getDecoderMethod() {
diff --git a/src/core/lombok/javac/handlers/HandleBuilder.java b/src/core/lombok/javac/handlers/HandleBuilder.java
index 4c670433..157828a0 100644
--- a/src/core/lombok/javac/handlers/HandleBuilder.java
+++ b/src/core/lombok/javac/handlers/HandleBuilder.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013-2015 The Project Lombok Authors.
+ * Copyright (C) 2013-2017 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
@@ -85,9 +85,12 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> {
JCExpression type;
Name rawName;
Name name;
+ Name nameOfDefaultProvider;
+ Name nameOfSetFlag;
SingularData singularData;
ObtainVia obtainVia;
JavacNode obtainViaNode;
+ JavacNode originalFieldNode;
java.util.List<JavacNode> createdFields = new ArrayList<JavacNode>();
}
@@ -139,17 +142,39 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> {
ListBuffer<JavacNode> allFields = new ListBuffer<JavacNode>();
@SuppressWarnings("deprecation")
boolean valuePresent = (hasAnnotation(lombok.Value.class, parent) || hasAnnotation(lombok.experimental.Value.class, parent));
- for (JavacNode fieldNode : HandleConstructor.findAllFields(tdParent)) {
+ for (JavacNode fieldNode : HandleConstructor.findAllFields(tdParent, true)) {
JCVariableDecl fd = (JCVariableDecl) fieldNode.get();
- // final fields with an initializer cannot be written to, so they can't be 'builderized'. Unfortunately presence of @Value makes
- // non-final fields final, but @Value's handler hasn't done this yet, so we have to do this math ourselves.
- // Value will only skip making a field final if it has an explicit @NonFinal annotation, so we check for that.
- if (fd.init != null && valuePresent && !hasAnnotation(NonFinal.class, fieldNode)) continue;
+ JavacNode isDefault = findAnnotation(Builder.Default.class, fieldNode, true);
+ boolean isFinal = (fd.mods.flags & Flags.FINAL) != 0 || (valuePresent && !hasAnnotation(NonFinal.class, fieldNode));
BuilderFieldData bfd = new BuilderFieldData();
bfd.rawName = fd.name;
bfd.name = removePrefixFromField(fieldNode);
bfd.type = fd.vartype;
bfd.singularData = getSingularData(fieldNode);
+ bfd.originalFieldNode = fieldNode;
+
+ if (bfd.singularData != null && isDefault != null) {
+ isDefault.addError("@Builder.Default and @Singular cannot be mixed.");
+ isDefault = null;
+ }
+
+ if (fd.init == null && isDefault != null) {
+ isDefault.addWarning("@Builder.Default requires an initializing expression (' = something;').");
+ isDefault = null;
+ }
+
+ if (fd.init != null && isDefault == null) {
+ if (isFinal) continue;
+ fieldNode.addWarning("@Builder will ignore the initializing expression entirely. If you want the initializing expression to serve as default, add @Builder.Default. If it is not supposed to be settable during building, make the field final.");
+ }
+
+ if (isDefault != null) {
+ bfd.nameOfDefaultProvider = parent.toName("$default$" + bfd.name);
+ bfd.nameOfSetFlag = parent.toName(bfd.name + "$set");
+ JCMethodDecl md = generateDefaultProvider(bfd.nameOfDefaultProvider, fieldNode);
+ recursiveSetGeneratedBy(md, ast, annotationNode.getContext());
+ if (md != null) injectMethod(tdParent, md);
+ }
addObtainVia(bfd, fieldNode);
builderFields.add(bfd);
allFields.append(fieldNode);
@@ -290,6 +315,7 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> {
bfd.rawName = raw.name;
bfd.type = raw.vartype;
bfd.singularData = getSingularData(param);
+ bfd.originalFieldNode = param;
addObtainVia(bfd, param);
builderFields.add(bfd);
}
@@ -357,7 +383,7 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> {
}
if (methodExists(buildMethodName, builderType, -1) == MemberExistsResult.NOT_EXISTS) {
- JCMethodDecl md = generateBuildMethod(isStatic, buildMethodName, nameOfBuilderMethod, returnType, builderFields, builderType, thrownExceptions, ast, addCleaning);
+ JCMethodDecl md = generateBuildMethod(tdParent, isStatic, buildMethodName, nameOfBuilderMethod, returnType, builderFields, builderType, thrownExceptions, ast, addCleaning);
if (md != null) injectMethod(builderType, md);
}
@@ -477,7 +503,7 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> {
}
}
- statements.append(maker.Exec(maker.Assign(maker.Select(maker.Ident(type.toName("this")), type.toName("$lombokUnclean")), maker.Literal(CTC_BOOLEAN, false))));
+ statements.append(maker.Exec(maker.Assign(maker.Select(maker.Ident(type.toName("this")), type.toName("$lombokUnclean")), maker.Literal(CTC_BOOLEAN, 0))));
JCBlock body = maker.Block(0, statements.toList());
return maker.MethodDef(maker.Modifiers(Flags.PUBLIC), type.toName("$lombokClean"), maker.Type(Javac.createVoidType(type.getSymbolTable(), CTC_VOID)), List.<JCTypeParameter>nil(), List.<JCVariableDecl>nil(), List.<JCExpression>nil(), body, null);
/*
@@ -494,7 +520,7 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> {
*/
}
- private JCMethodDecl generateBuildMethod(boolean isStatic, String buildName, Name builderName, JCExpression returnType, java.util.List<BuilderFieldData> builderFields, JavacNode type, List<JCExpression> thrownExceptions, JCTree source, boolean addCleaning) {
+ private JCMethodDecl generateBuildMethod(JavacNode tdParent, boolean isStatic, String buildName, Name builderName, JCExpression returnType, java.util.List<BuilderFieldData> builderFields, JavacNode type, List<JCExpression> thrownExceptions, JCTree source, boolean addCleaning) {
JavacTreeMaker maker = type.getTreeMaker();
JCExpression call;
@@ -515,25 +541,28 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> {
ListBuffer<JCExpression> args = new ListBuffer<JCExpression>();
for (BuilderFieldData bfd : builderFields) {
- args.append(maker.Ident(bfd.name));
+ if (bfd.nameOfSetFlag != null) {
+ args.append(maker.Conditional(maker.Ident(bfd.nameOfSetFlag), maker.Ident(bfd.name),
+ maker.Apply(List.<JCExpression>nil(), maker.Select(maker.Ident(((JCClassDecl) tdParent.get()).name), bfd.nameOfDefaultProvider), List.<JCExpression>nil())));
+ } else {
+ args.append(maker.Ident(bfd.name));
+ }
}
if (addCleaning) {
- statements.append(maker.Exec(maker.Assign(maker.Select(maker.Ident(type.toName("this")), type.toName("$lombokUnclean")), maker.Literal(CTC_BOOLEAN, true))));
+ statements.append(maker.Exec(maker.Assign(maker.Select(maker.Ident(type.toName("this")), type.toName("$lombokUnclean")), maker.Literal(CTC_BOOLEAN, 1))));
}
if (builderName == null) {
call = maker.NewClass(null, List.<JCExpression>nil(), returnType, args.toList(), null);
statements.append(maker.Return(call));
} else {
-
ListBuffer<JCExpression> typeParams = new ListBuffer<JCExpression>();
for (JCTypeParameter tp : ((JCClassDecl) type.get()).typarams) {
typeParams.append(maker.Ident(tp.name));
}
JCExpression callee = maker.Ident(((JCClassDecl) type.up().get()).name);
- if (!isStatic)
- callee = maker.Select(callee, type.up().toName("this"));
+ if (!isStatic) callee = maker.Select(callee, type.up().toName("this"));
JCExpression fn = maker.Select(callee, builderName);
call = maker.Apply(typeParams.toList(), fn, args.toList());
if (returnType instanceof JCPrimitiveTypeTree && CTC_VOID.equals(typeTag(returnType))) {
@@ -548,6 +577,18 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> {
return maker.MethodDef(maker.Modifiers(Flags.PUBLIC), type.toName(buildName), returnType, List.<JCTypeParameter>nil(), List.<JCVariableDecl>nil(), thrownExceptions, body, null);
}
+ public JCMethodDecl generateDefaultProvider(Name methodName, JavacNode fieldNode) {
+ JavacTreeMaker maker = fieldNode.getTreeMaker();
+ JCVariableDecl field = (JCVariableDecl) fieldNode.get();
+
+ JCStatement statement = maker.Return(field.init);
+ field.init = null;
+
+ JCBlock body = maker.Block(0, List.<JCStatement>of(statement));
+ int modifiers = Flags.PRIVATE | Flags.STATIC;
+ return maker.MethodDef(maker.Modifiers(modifiers), methodName, cloneType(maker, field.vartype, field, fieldNode.getContext()), List.<JCTypeParameter>nil(), List.<JCVariableDecl>nil(), List.<JCExpression>nil(), body, null);
+ }
+
public JCMethodDecl generateBuilderMethod(boolean isStatic, String builderMethodName, String builderClassName, JavacNode source, JavacNode type, List<JCTypeParameter> typeParams) {
JavacTreeMaker maker = type.getTreeMaker();
@@ -572,36 +613,43 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> {
if (child.getKind() == Kind.FIELD) existing.add(child);
}
- top:
for (int i = len - 1; i >= 0; i--) {
BuilderFieldData bfd = builderFields.get(i);
if (bfd.singularData != null && bfd.singularData.getSingularizer() != null) {
bfd.createdFields.addAll(bfd.singularData.getSingularizer().generateFields(bfd.singularData, builderType, source));
} else {
+ JavacNode field = null, setFlag = null;
for (JavacNode exists : existing) {
Name n = ((JCVariableDecl) exists.get()).name;
- if (n.equals(bfd.name)) {
- bfd.createdFields.add(exists);
- continue top;
- }
+ if (n.equals(bfd.name)) field = exists;
+ if (n.equals(bfd.nameOfSetFlag)) setFlag = exists;
}
JavacTreeMaker maker = builderType.getTreeMaker();
- JCModifiers mods = maker.Modifiers(Flags.PRIVATE);
- JCVariableDecl newField = maker.VarDef(mods, bfd.name, cloneType(maker, bfd.type, source, builderType.getContext()), null);
- bfd.createdFields.add(injectFieldAndMarkGenerated(builderType, newField));
+ if (field == null) {
+ JCModifiers mods = maker.Modifiers(Flags.PRIVATE);
+ JCVariableDecl newField = maker.VarDef(mods, bfd.name, cloneType(maker, bfd.type, source, builderType.getContext()), null);
+ field = injectFieldAndMarkGenerated(builderType, newField);
+ }
+ if (setFlag == null && bfd.nameOfSetFlag != null) {
+ JCModifiers mods = maker.Modifiers(Flags.PRIVATE);
+ JCVariableDecl newField = maker.VarDef(mods, bfd.nameOfSetFlag, maker.TypeIdent(CTC_BOOLEAN), null);
+ injectFieldAndMarkGenerated(builderType, newField);
+ }
+ bfd.createdFields.add(field);
}
}
}
public void makeSetterMethodsForBuilder(JavacNode builderType, BuilderFieldData fieldNode, JavacNode source, boolean fluent, boolean chain) {
+ boolean deprecate = isFieldDeprecated(fieldNode.originalFieldNode);
if (fieldNode.singularData == null || fieldNode.singularData.getSingularizer() == null) {
- makeSimpleSetterMethodForBuilder(builderType, fieldNode.createdFields.get(0), source, fluent, chain);
+ makeSimpleSetterMethodForBuilder(builderType, deprecate, fieldNode.createdFields.get(0), fieldNode.nameOfSetFlag, source, fluent, chain);
} else {
- fieldNode.singularData.getSingularizer().generateMethods(fieldNode.singularData, builderType, source.get(), fluent, chain);
+ fieldNode.singularData.getSingularizer().generateMethods(fieldNode.singularData, deprecate, builderType, source.get(), fluent, chain);
}
}
- private void makeSimpleSetterMethodForBuilder(JavacNode builderType, JavacNode fieldNode, JavacNode source, boolean fluent, boolean chain) {
+ private void makeSimpleSetterMethodForBuilder(JavacNode builderType, boolean deprecate, JavacNode fieldNode, Name nameOfSetFlag, JavacNode source, boolean fluent, boolean chain) {
Name fieldName = ((JCVariableDecl) fieldNode.get()).name;
for (JavacNode child : builderType.down()) {
@@ -614,7 +662,9 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> {
String setterName = fluent ? fieldNode.getName() : HandlerUtil.buildAccessorName("set", fieldNode.getName());
JavacTreeMaker maker = fieldNode.getTreeMaker();
- JCMethodDecl newMethod = HandleSetter.createSetter(Flags.PUBLIC, fieldNode, maker, setterName, chain, source, List.<JCAnnotation>nil(), List.<JCAnnotation>nil());
+
+ JCMethodDecl newMethod = HandleSetter.createSetter(Flags.PUBLIC, deprecate, fieldNode, maker, setterName, nameOfSetFlag, chain, source, List.<JCAnnotation>nil(), List.<JCAnnotation>nil());
+
injectMethod(builderType, newMethod);
}
diff --git a/src/core/lombok/javac/handlers/HandleBuilderDefault.java b/src/core/lombok/javac/handlers/HandleBuilderDefault.java
new file mode 100644
index 00000000..733aea5a
--- /dev/null
+++ b/src/core/lombok/javac/handlers/HandleBuilderDefault.java
@@ -0,0 +1,29 @@
+package lombok.javac.handlers;
+
+import static lombok.javac.handlers.JavacHandlerUtil.*;
+
+import org.mangosdk.spi.ProviderFor;
+
+import com.sun.tools.javac.tree.JCTree.JCAnnotation;
+
+import lombok.Builder;
+import lombok.core.AST.Kind;
+import lombok.core.AnnotationValues;
+import lombok.core.HandlerPriority;
+import lombok.javac.JavacAnnotationHandler;
+import lombok.javac.JavacNode;
+
+@ProviderFor(JavacAnnotationHandler.class)
+@HandlerPriority(-1025) //HandleBuilder's level, minus one.
+public class HandleBuilderDefault extends JavacAnnotationHandler<Builder.Default> {
+ @SuppressWarnings("deprecation")
+ @Override public void handle(AnnotationValues<Builder.Default> annotation, JCAnnotation ast, JavacNode annotationNode) {
+ JavacNode annotatedField = annotationNode.up();
+ if (annotatedField.getKind() != Kind.FIELD) return;
+ JavacNode classWithAnnotatedField = annotatedField.up();
+ if (!hasAnnotation(Builder.class, classWithAnnotatedField) && !hasAnnotation(lombok.experimental.Builder.class, classWithAnnotatedField)) {
+ annotationNode.addWarning("@Builder.Default requires @Builder on the class for it to mean anything.");
+ deleteAnnotationIfNeccessary(annotationNode, Builder.Default.class);
+ }
+ }
+}
diff --git a/src/core/lombok/javac/handlers/HandleConstructor.java b/src/core/lombok/javac/handlers/HandleConstructor.java
index 25e96d75..929de3cd 100644
--- a/src/core/lombok/javac/handlers/HandleConstructor.java
+++ b/src/core/lombok/javac/handlers/HandleConstructor.java
@@ -151,6 +151,10 @@ public class HandleConstructor {
}
public static List<JavacNode> findAllFields(JavacNode typeNode) {
+ return findAllFields(typeNode, false);
+ }
+
+ public static List<JavacNode> findAllFields(JavacNode typeNode, boolean evenFinalInitialized) {
ListBuffer<JavacNode> fields = new ListBuffer<JavacNode>();
for (JavacNode child : typeNode.down()) {
if (child.getKind() != Kind.FIELD) continue;
@@ -162,7 +166,7 @@ public class HandleConstructor {
if ((fieldFlags & Flags.STATIC) != 0) continue;
//Skip initialized final fields
boolean isFinal = (fieldFlags & Flags.FINAL) != 0;
- if (!isFinal || fieldDecl.init == null) fields.append(child);
+ if (evenFinalInitialized || !isFinal || fieldDecl.init == null) fields.append(child);
}
return fields.toList();
}
@@ -295,7 +299,7 @@ public class HandleConstructor {
}
JCModifiers mods = maker.Modifiers(toJavacModifier(level), List.<JCAnnotation>nil());
- if (!allToDefault && !suppressConstructorProperties && level != AccessLevel.PRIVATE && level != AccessLevel.PACKAGE && !isLocalType(typeNode) && LombokOptionsFactory.getDelombokOptions(typeNode.getContext()).getFormatPreferences().generateConstructorProperties()) {
+ if (!allToDefault && !suppressConstructorProperties && !isLocalType(typeNode) && LombokOptionsFactory.getDelombokOptions(typeNode.getContext()).getFormatPreferences().generateConstructorProperties()) {
addConstructorProperties(mods, typeNode, fields);
}
if (onConstructor != null) mods.annotations = mods.annotations.appendList(copyAnnotations(onConstructor));
diff --git a/src/core/lombok/javac/handlers/HandleEqualsAndHashCode.java b/src/core/lombok/javac/handlers/HandleEqualsAndHashCode.java
index 6df56ed6..4bd1ce4b 100644
--- a/src/core/lombok/javac/handlers/HandleEqualsAndHashCode.java
+++ b/src/core/lombok/javac/handlers/HandleEqualsAndHashCode.java
@@ -121,7 +121,10 @@ public class HandleEqualsAndHashCode extends JavacAnnotationHandler<EqualsAndHas
return;
}
- generateMethods(typeNode, source, null, null, null, false, FieldAccess.GETTER, List.<JCAnnotation>nil());
+ Boolean doNotUseGettersConfiguration = typeNode.getAst().readConfiguration(ConfigurationKeys.EQUALS_AND_HASH_CODE_DO_NOT_USE_GETTERS);
+ FieldAccess access = doNotUseGettersConfiguration == null || !doNotUseGettersConfiguration ? FieldAccess.GETTER : FieldAccess.PREFER_FIELD;
+
+ generateMethods(typeNode, source, null, null, null, false, access, List.<JCAnnotation>nil());
}
public void generateMethods(JavacNode typeNode, JavacNode source, List<String> excludes, List<String> includes,
diff --git a/src/core/lombok/javac/handlers/HandleSetter.java b/src/core/lombok/javac/handlers/HandleSetter.java
index e766127a..1453aa27 100644
--- a/src/core/lombok/javac/handlers/HandleSetter.java
+++ b/src/core/lombok/javac/handlers/HandleSetter.java
@@ -206,10 +206,10 @@ public class HandleSetter extends JavacAnnotationHandler<Setter> {
public static JCMethodDecl createSetter(long access, JavacNode field, JavacTreeMaker treeMaker, JavacNode source, List<JCAnnotation> onMethod, List<JCAnnotation> onParam) {
String setterName = toSetterName(field);
boolean returnThis = shouldReturnThis(field);
- return createSetter(access, field, treeMaker, setterName, returnThis, source, onMethod, onParam);
+ return createSetter(access, false, field, treeMaker, setterName, null, returnThis, source, onMethod, onParam);
}
- public static JCMethodDecl createSetter(long access, JavacNode field, JavacTreeMaker treeMaker, String setterName, boolean shouldReturnThis, JavacNode source, List<JCAnnotation> onMethod, List<JCAnnotation> onParam) {
+ public static JCMethodDecl createSetter(long access, boolean deprecate, JavacNode field, JavacTreeMaker treeMaker, String setterName, Name booleanFieldToSet, boolean shouldReturnThis, JavacNode source, List<JCAnnotation> onMethod, List<JCAnnotation> onParam) {
if (setterName == null) return null;
JCVariableDecl fieldDecl = (JCVariableDecl) field.get();
@@ -235,6 +235,11 @@ public class HandleSetter extends JavacAnnotationHandler<Setter> {
statements.append(treeMaker.Exec(assign));
}
+ if (booleanFieldToSet != null) {
+ JCAssign setBool = treeMaker.Assign(treeMaker.Ident(booleanFieldToSet), treeMaker.Literal(CTC_BOOLEAN, 1));
+ statements.append(treeMaker.Exec(setBool));
+ }
+
JCExpression methodType = null;
if (shouldReturnThis) {
methodType = cloneSelfType(field);
@@ -258,7 +263,7 @@ public class HandleSetter extends JavacAnnotationHandler<Setter> {
JCExpression annotationMethodDefaultValue = null;
List<JCAnnotation> annsOnMethod = copyAnnotations(onMethod);
- if (isFieldDeprecated(field)) {
+ if (isFieldDeprecated(field) || deprecate) {
annsOnMethod = annsOnMethod.prepend(treeMaker.Annotation(genJavaLangTypeRef(field, "Deprecated"), List.<JCExpression>nil()));
}
diff --git a/src/core/lombok/javac/handlers/HandleToString.java b/src/core/lombok/javac/handlers/HandleToString.java
index 743e7b26..897d5f2c 100644
--- a/src/core/lombok/javac/handlers/HandleToString.java
+++ b/src/core/lombok/javac/handlers/HandleToString.java
@@ -117,7 +117,11 @@ public class HandleToString extends JavacAnnotationHandler<ToString> {
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);
+
+ Boolean doNotUseGettersConfiguration = typeNode.getAst().readConfiguration(ConfigurationKeys.TO_STRING_DO_NOT_USE_GETTERS);
+ FieldAccess access = doNotUseGettersConfiguration == null || !doNotUseGettersConfiguration ? FieldAccess.GETTER : FieldAccess.PREFER_FIELD;
+
+ generateToString(typeNode, errorNode, null, null, includeFieldNames, null, false, access);
}
public void generateToString(JavacNode typeNode, JavacNode source, List<String> excludes, List<String> includes,
diff --git a/src/core/lombok/javac/handlers/JavacHandlerUtil.java b/src/core/lombok/javac/handlers/JavacHandlerUtil.java
index 68d8061c..b4dcb097 100644
--- a/src/core/lombok/javac/handlers/JavacHandlerUtil.java
+++ b/src/core/lombok/javac/handlers/JavacHandlerUtil.java
@@ -191,6 +191,27 @@ public class JavacHandlerUtil {
}
}
+ static JavacNode findAnnotation(Class<? extends Annotation> type, JavacNode node, boolean delete) {
+ if (node == null) return null;
+ if (type == null) return null;
+ switch (node.getKind()) {
+ case ARGUMENT:
+ case FIELD:
+ case LOCAL:
+ case TYPE:
+ case METHOD:
+ for (JavacNode child : node.down()) {
+ if (annotationTypeMatches(type, child)) {
+ if (delete) deleteAnnotationIfNeccessary(child, type);
+ return child;
+ }
+ }
+ // intentional fallthrough
+ default:
+ return null;
+ }
+ }
+
/**
* Checks if the Annotation AST Node provided is likely to be an instance of the provided annotation type.
*
@@ -222,6 +243,7 @@ public class JavacHandlerUtil {
* @return {@code true} if a field is marked deprecated, either by {@code @Deprecated} or in javadoc, otherwise {@code false}
*/
public static boolean isFieldDeprecated(JavacNode field) {
+ if (!(field.get() instanceof JCVariableDecl)) return false;
JCVariableDecl fieldNode = (JCVariableDecl) field.get();
if ((fieldNode.mods.flags & Flags.DEPRECATED) != 0) {
return true;
diff --git a/src/core/lombok/javac/handlers/JavacSingularsRecipes.java b/src/core/lombok/javac/handlers/JavacSingularsRecipes.java
index c6d601bd..6a76e1dd 100644
--- a/src/core/lombok/javac/handlers/JavacSingularsRecipes.java
+++ b/src/core/lombok/javac/handlers/JavacSingularsRecipes.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2015 The Project Lombok Authors.
+ * Copyright (C) 2015-2017 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
@@ -38,9 +38,12 @@ import lombok.javac.JavacTreeMaker;
import com.sun.source.tree.Tree.Kind;
import com.sun.tools.javac.code.BoundKind;
+import com.sun.tools.javac.code.Flags;
import com.sun.tools.javac.tree.JCTree;
+import com.sun.tools.javac.tree.JCTree.JCAnnotation;
import com.sun.tools.javac.tree.JCTree.JCExpression;
import com.sun.tools.javac.tree.JCTree.JCMethodDecl;
+import com.sun.tools.javac.tree.JCTree.JCModifiers;
import com.sun.tools.javac.tree.JCTree.JCStatement;
import com.sun.tools.javac.tree.JCTree.JCVariableDecl;
import com.sun.tools.javac.tree.JCTree.JCWildcard;
@@ -141,6 +144,11 @@ public class JavacSingularsRecipes {
public static abstract class JavacSingularizer {
public abstract LombokImmutableList<String> getSupportedTypes();
+ protected JCModifiers makeMods(JavacTreeMaker maker, JavacNode node, boolean deprecate) {
+ if (deprecate) return maker.Modifiers(Flags.PUBLIC, List.<JCAnnotation>of(maker.Annotation(genJavaLangTypeRef(node, "Deprecated"), List.<JCExpression>nil())));
+ return maker.Modifiers(Flags.PUBLIC);
+ }
+
/** Checks if any of the to-be-generated nodes (fields, methods) already exist. If so, errors on these (singulars don't support manually writing some of it, and returns true). */
public boolean checkForAlreadyExistingNodesAndGenerateError(JavacNode builderType, SingularData data) {
for (JavacNode child : builderType.down()) {
@@ -186,7 +194,7 @@ public class JavacSingularsRecipes {
}
public abstract java.util.List<JavacNode> generateFields(SingularData data, JavacNode builderType, JCTree source);
- public abstract void generateMethods(SingularData data, JavacNode builderType, JCTree source, boolean fluent, boolean chain);
+ public abstract void generateMethods(SingularData data, boolean deprecate, JavacNode builderType, JCTree source, boolean fluent, boolean chain);
public abstract void appendBuildCode(SingularData data, JavacNode builderType, JCTree source, ListBuffer<JCStatement> statements, Name targetVariableName);
public boolean requiresCleaning() {
diff --git a/src/core/lombok/javac/handlers/singulars/JavacGuavaSingularizer.java b/src/core/lombok/javac/handlers/singulars/JavacGuavaSingularizer.java
index fba4c80e..0ab7da54 100644
--- a/src/core/lombok/javac/handlers/singulars/JavacGuavaSingularizer.java
+++ b/src/core/lombok/javac/handlers/singulars/JavacGuavaSingularizer.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2015 The Project Lombok Authors.
+ * Copyright (C) 2015-2017 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
@@ -70,24 +70,24 @@ abstract class JavacGuavaSingularizer extends JavacSingularizer {
return Collections.singletonList(injectFieldAndMarkGenerated(builderType, buildField));
}
- @Override public void generateMethods(SingularData data, JavacNode builderType, JCTree source, boolean fluent, boolean chain) {
+ @Override public void generateMethods(SingularData data, boolean deprecate, JavacNode builderType, JCTree source, boolean fluent, boolean chain) {
JavacTreeMaker maker = builderType.getTreeMaker();
Symtab symbolTable = builderType.getSymbolTable();
JCExpression returnType = chain ? cloneSelfType(builderType) : maker.Type(createVoidType(symbolTable, CTC_VOID));
JCStatement returnStatement = chain ? maker.Return(maker.Ident(builderType.toName("this"))) : null;
- generateSingularMethod(maker, returnType, returnStatement, data, builderType, source, fluent);
+ generateSingularMethod(deprecate, maker, returnType, returnStatement, data, builderType, source, fluent);
returnType = chain ? cloneSelfType(builderType) : maker.Type(createVoidType(symbolTable, CTC_VOID));
returnStatement = chain ? maker.Return(maker.Ident(builderType.toName("this"))) : null;
- generatePluralMethod(maker, returnType, returnStatement, data, builderType, source, fluent);
+ generatePluralMethod(deprecate, maker, returnType, returnStatement, data, builderType, source, fluent);
returnType = chain ? cloneSelfType(builderType) : maker.Type(createVoidType(symbolTable, CTC_VOID));
returnStatement = chain ? maker.Return(maker.Ident(builderType.toName("this"))) : null;
- generateClearMethod(maker, returnType, returnStatement, data, builderType, source);
+ generateClearMethod(deprecate, maker, returnType, returnStatement, data, builderType, source);
}
- private void generateClearMethod(JavacTreeMaker maker, JCExpression returnType, JCStatement returnStatement, SingularData data, JavacNode builderType, JCTree source) {
- JCModifiers mods = maker.Modifiers(Flags.PUBLIC);
+ private void generateClearMethod(boolean deprecate, JavacTreeMaker maker, JCExpression returnType, JCStatement returnStatement, SingularData data, JavacNode builderType, JCTree source) {
+ JCModifiers mods = makeMods(maker, builderType, deprecate);
List<JCTypeParameter> typeParams = List.nil();
List<JCExpression> thrown = List.nil();
List<JCVariableDecl> params = List.nil();
@@ -102,7 +102,7 @@ abstract class JavacGuavaSingularizer extends JavacSingularizer {
injectMethod(builderType, method);
}
- void generateSingularMethod(JavacTreeMaker maker, JCExpression returnType, JCStatement returnStatement, SingularData data, JavacNode builderType, JCTree source, boolean fluent) {
+ void generateSingularMethod(boolean deprecate, JavacTreeMaker maker, JCExpression returnType, JCStatement returnStatement, SingularData data, JavacNode builderType, JCTree source, boolean fluent) {
List<JCTypeParameter> typeParams = List.nil();
List<JCExpression> thrown = List.nil();
@@ -114,7 +114,7 @@ abstract class JavacGuavaSingularizer extends JavacSingularizer {
names[i] = s.isEmpty() ? n : builderType.toName(s);
}
- JCModifiers mods = maker.Modifiers(Flags.PUBLIC);
+ JCModifiers mods = makeMods(maker, builderType, deprecate);
ListBuffer<JCStatement> statements = new ListBuffer<JCStatement>();
statements.append(createConstructBuilderVarIfNeeded(maker, data, builderType, source));
JCExpression thisDotFieldDotAdd = chainDots(builderType, "this", data.getPluralName().toString(), getAddMethodName());
@@ -141,11 +141,10 @@ abstract class JavacGuavaSingularizer extends JavacSingularizer {
injectMethod(builderType, method);
}
- protected void generatePluralMethod(JavacTreeMaker maker, JCExpression returnType, JCStatement returnStatement, SingularData data, JavacNode builderType, JCTree source, boolean fluent) {
+ protected void generatePluralMethod(boolean deprecate, JavacTreeMaker maker, JCExpression returnType, JCStatement returnStatement, SingularData data, JavacNode builderType, JCTree source, boolean fluent) {
List<JCTypeParameter> typeParams = List.nil();
List<JCExpression> thrown = List.nil();
-
- JCModifiers mods = maker.Modifiers(Flags.PUBLIC);
+ JCModifiers mods = makeMods(maker, builderType, deprecate);
ListBuffer<JCStatement> statements = new ListBuffer<JCStatement>();
statements.append(createConstructBuilderVarIfNeeded(maker, data, builderType, source));
JCExpression thisDotFieldDotAddAll = chainDots(builderType, "this", data.getPluralName().toString(), getAddMethodName() + "All");
diff --git a/src/core/lombok/javac/handlers/singulars/JavacJavaUtilListSetSingularizer.java b/src/core/lombok/javac/handlers/singulars/JavacJavaUtilListSetSingularizer.java
index 7beb29cb..196ce45d 100644
--- a/src/core/lombok/javac/handlers/singulars/JavacJavaUtilListSetSingularizer.java
+++ b/src/core/lombok/javac/handlers/singulars/JavacJavaUtilListSetSingularizer.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2015 The Project Lombok Authors.
+ * Copyright (C) 2015-2017 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
@@ -76,9 +76,9 @@ abstract class JavacJavaUtilListSetSingularizer extends JavacJavaUtilSingularize
return Collections.singletonList(injectFieldAndMarkGenerated(builderType, buildField));
}
- @Override public void generateMethods(SingularData data, JavacNode builderType, JCTree source, boolean fluent, boolean chain) {
+ @Override public void generateMethods(SingularData data, boolean deprecate, JavacNode builderType, JCTree source, boolean fluent, boolean chain) {
if (useGuavaInstead(builderType)) {
- guavaListSetSingularizer.generateMethods(data, builderType, source, fluent, chain);
+ guavaListSetSingularizer.generateMethods(data, deprecate, builderType, source, fluent, chain);
return;
}
@@ -88,19 +88,19 @@ abstract class JavacJavaUtilListSetSingularizer extends JavacJavaUtilSingularize
JCExpression returnType = chain ? cloneSelfType(builderType) : maker.Type(createVoidType(symbolTable, CTC_VOID));
JCStatement returnStatement = chain ? maker.Return(maker.Ident(thisName)) : null;
- generateSingularMethod(maker, returnType, returnStatement, data, builderType, source, fluent);
+ generateSingularMethod(deprecate, maker, returnType, returnStatement, data, builderType, source, fluent);
returnType = chain ? cloneSelfType(builderType) : maker.Type(createVoidType(symbolTable, CTC_VOID));
returnStatement = chain ? maker.Return(maker.Ident(thisName)) : null;
- generatePluralMethod(maker, returnType, returnStatement, data, builderType, source, fluent);
+ generatePluralMethod(deprecate, maker, returnType, returnStatement, data, builderType, source, fluent);
returnType = chain ? cloneSelfType(builderType) : maker.Type(createVoidType(symbolTable, CTC_VOID));
returnStatement = chain ? maker.Return(maker.Ident(thisName)) : null;
- generateClearMethod(maker, returnType, returnStatement, data, builderType, source);
+ generateClearMethod(deprecate, maker, returnType, returnStatement, data, builderType, source);
}
- private void generateClearMethod(JavacTreeMaker maker, JCExpression returnType, JCStatement returnStatement, SingularData data, JavacNode builderType, JCTree source) {
- JCModifiers mods = maker.Modifiers(Flags.PUBLIC);
+ private void generateClearMethod(boolean deprecate, JavacTreeMaker maker, JCExpression returnType, JCStatement returnStatement, SingularData data, JavacNode builderType, JCTree source) {
+ JCModifiers mods = makeMods(maker, builderType, deprecate);
List<JCTypeParameter> typeParams = List.nil();
List<JCExpression> thrown = List.nil();
List<JCVariableDecl> params = List.nil();
@@ -119,11 +119,10 @@ abstract class JavacJavaUtilListSetSingularizer extends JavacJavaUtilSingularize
injectMethod(builderType, method);
}
- void generateSingularMethod(JavacTreeMaker maker, JCExpression returnType, JCStatement returnStatement, SingularData data, JavacNode builderType, JCTree source, boolean fluent) {
+ void generateSingularMethod(boolean deprecate, JavacTreeMaker maker, JCExpression returnType, JCStatement returnStatement, SingularData data, JavacNode builderType, JCTree source, boolean fluent) {
List<JCTypeParameter> typeParams = List.nil();
List<JCExpression> thrown = List.nil();
-
- JCModifiers mods = maker.Modifiers(Flags.PUBLIC);
+ JCModifiers mods = makeMods(maker, builderType, deprecate);
ListBuffer<JCStatement> statements = new ListBuffer<JCStatement>();
statements.append(createConstructBuilderVarIfNeeded(maker, data, builderType, false, source));
JCExpression thisDotFieldDotAdd = chainDots(builderType, "this", data.getPluralName().toString(), "add");
@@ -140,11 +139,10 @@ abstract class JavacJavaUtilListSetSingularizer extends JavacJavaUtilSingularize
injectMethod(builderType, method);
}
- void generatePluralMethod(JavacTreeMaker maker, JCExpression returnType, JCStatement returnStatement, SingularData data, JavacNode builderType, JCTree source, boolean fluent) {
+ void generatePluralMethod(boolean deprecate, JavacTreeMaker maker, JCExpression returnType, JCStatement returnStatement, SingularData data, JavacNode builderType, JCTree source, boolean fluent) {
List<JCTypeParameter> typeParams = List.nil();
List<JCExpression> thrown = List.nil();
-
- JCModifiers mods = maker.Modifiers(Flags.PUBLIC);
+ JCModifiers mods = makeMods(maker, builderType, deprecate);
ListBuffer<JCStatement> statements = new ListBuffer<JCStatement>();
statements.append(createConstructBuilderVarIfNeeded(maker, data, builderType, false, source));
JCExpression thisDotFieldDotAdd = chainDots(builderType, "this", data.getPluralName().toString(), "addAll");
diff --git a/src/core/lombok/javac/handlers/singulars/JavacJavaUtilMapSingularizer.java b/src/core/lombok/javac/handlers/singulars/JavacJavaUtilMapSingularizer.java
index 93b120e1..fd699275 100644
--- a/src/core/lombok/javac/handlers/singulars/JavacJavaUtilMapSingularizer.java
+++ b/src/core/lombok/javac/handlers/singulars/JavacJavaUtilMapSingularizer.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2015 The Project Lombok Authors.
+ * Copyright (C) 2015-2017 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
@@ -101,9 +101,9 @@ public class JavacJavaUtilMapSingularizer extends JavacJavaUtilSingularizer {
return Arrays.asList(keyFieldNode, valueFieldNode);
}
- @Override public void generateMethods(SingularData data, JavacNode builderType, JCTree source, boolean fluent, boolean chain) {
+ @Override public void generateMethods(SingularData data, boolean deprecate, JavacNode builderType, JCTree source, boolean fluent, boolean chain) {
if (useGuavaInstead(builderType)) {
- guavaMapSingularizer.generateMethods(data, builderType, source, fluent, chain);
+ guavaMapSingularizer.generateMethods(data, deprecate, builderType, source, fluent, chain);
return;
}
@@ -112,19 +112,20 @@ public class JavacJavaUtilMapSingularizer extends JavacJavaUtilSingularizer {
JCExpression returnType = chain ? cloneSelfType(builderType) : maker.Type(createVoidType(symbolTable, CTC_VOID));
JCStatement returnStatement = chain ? maker.Return(maker.Ident(builderType.toName("this"))) : null;
- generateSingularMethod(maker, returnType, returnStatement, data, builderType, source, fluent);
+ generateSingularMethod(deprecate, maker, returnType, returnStatement, data, builderType, source, fluent);
returnType = chain ? cloneSelfType(builderType) : maker.Type(createVoidType(symbolTable, CTC_VOID));
returnStatement = chain ? maker.Return(maker.Ident(builderType.toName("this"))) : null;
- generatePluralMethod(maker, returnType, returnStatement, data, builderType, source, fluent);
+ generatePluralMethod(deprecate, maker, returnType, returnStatement, data, builderType, source, fluent);
returnType = chain ? cloneSelfType(builderType) : maker.Type(createVoidType(symbolTable, CTC_VOID));
returnStatement = chain ? maker.Return(maker.Ident(builderType.toName("this"))) : null;
- generateClearMethod(maker, returnType, returnStatement, data, builderType, source);
+ generateClearMethod(deprecate, maker, returnType, returnStatement, data, builderType, source);
}
- private void generateClearMethod(JavacTreeMaker maker, JCExpression returnType, JCStatement returnStatement, SingularData data, JavacNode builderType, JCTree source) {
- JCModifiers mods = maker.Modifiers(Flags.PUBLIC);
+ private void generateClearMethod(boolean deprecate, JavacTreeMaker maker, JCExpression returnType, JCStatement returnStatement, SingularData data, JavacNode builderType, JCTree source) {
+ JCModifiers mods = makeMods(maker, builderType, deprecate);
+
List<JCTypeParameter> typeParams = List.nil();
List<JCExpression> thrown = List.nil();
List<JCVariableDecl> params = List.nil();
@@ -146,10 +147,11 @@ public class JavacJavaUtilMapSingularizer extends JavacJavaUtilSingularizer {
injectMethod(builderType, method);
}
- private void generateSingularMethod(JavacTreeMaker maker, JCExpression returnType, JCStatement returnStatement, SingularData data, JavacNode builderType, JCTree source, boolean fluent) {
+ private void generateSingularMethod(boolean deprecate, JavacTreeMaker maker, JCExpression returnType, JCStatement returnStatement, SingularData data, JavacNode builderType, JCTree source, boolean fluent) {
List<JCTypeParameter> typeParams = List.nil();
List<JCExpression> thrown = List.nil();
- JCModifiers mods = maker.Modifiers(Flags.PUBLIC);
+ JCModifiers mods = makeMods(maker, builderType, deprecate);
+
ListBuffer<JCStatement> statements = new ListBuffer<JCStatement>();
statements.append(createConstructBuilderVarIfNeeded(maker, data, builderType, true, source));
Name keyName = builderType.toName(data.getSingularName().toString() + "Key");
@@ -178,10 +180,10 @@ public class JavacJavaUtilMapSingularizer extends JavacJavaUtilSingularizer {
injectMethod(builderType, method);
}
- private void generatePluralMethod(JavacTreeMaker maker, JCExpression returnType, JCStatement returnStatement, SingularData data, JavacNode builderType, JCTree source, boolean fluent) {
+ private void generatePluralMethod(boolean deprecate, JavacTreeMaker maker, JCExpression returnType, JCStatement returnStatement, SingularData data, JavacNode builderType, JCTree source, boolean fluent) {
List<JCTypeParameter> typeParams = List.nil();
List<JCExpression> jceBlank = List.nil();
- JCModifiers mods = maker.Modifiers(Flags.PUBLIC);
+ JCModifiers mods = makeMods(maker, builderType, deprecate);
ListBuffer<JCStatement> statements = new ListBuffer<JCStatement>();
statements.append(createConstructBuilderVarIfNeeded(maker, data, builderType, true, source));
long paramFlags = JavacHandlerUtil.addFinalIfNeeded(Flags.PARAMETER, builderType.getContext());
diff --git a/src/core/lombok/javac/handlers/singulars/JavacJavaUtilSingularizer.java b/src/core/lombok/javac/handlers/singulars/JavacJavaUtilSingularizer.java
index 25669721..0589ac34 100644
--- a/src/core/lombok/javac/handlers/singulars/JavacJavaUtilSingularizer.java
+++ b/src/core/lombok/javac/handlers/singulars/JavacJavaUtilSingularizer.java
@@ -165,6 +165,9 @@ abstract class JavacJavaUtilSingularizer extends JavacSingularizer {
JCExpression pluralnameDotPut = maker.Select(maker.Ident(data.getPluralName()), builderType.toName("put"));
JCExpression arg1 = maker.Apply(jceBlank, chainDots(builderType, "this", data.getPluralName() + "$key", "get"), List.<JCExpression>of(maker.Ident(ivar)));
JCExpression arg2 = maker.Apply(jceBlank, chainDots(builderType, "this", data.getPluralName() + "$value", "get"), List.<JCExpression>of(maker.Ident(ivar)));
+ // [jdk9] We add an unneccessary (V) cast here. Not doing so gives an error in javac (build 9-ea+156-jigsaw-nightly-h6072-20170212):
+ // error: method put in interface Map<K#2,V#2> cannot be applied to given types;
+ arg2 = maker.TypeCast(createTypeArgs(2, false, builderType, data.getTypeArgs(), source).get(1), arg2);
JCStatement putStatement = maker.Exec(maker.Apply(jceBlank, pluralnameDotPut, List.of(arg1, arg2)));
JCStatement forInit = maker.VarDef(maker.Modifiers(0), ivar, maker.TypeIdent(CTC_INT), maker.Literal(CTC_INT, 0));
JCExpression checkExpr = maker.Binary(CTC_LESS_THAN, maker.Ident(ivar), getSize(maker, builderType, keyVarName, nullGuard, true));
diff --git a/src/core/lombok/package-info.java b/src/core/lombok/package-info.java
index 5e34c914..1c01dd0d 100644
--- a/src/core/lombok/package-info.java
+++ b/src/core/lombok/package-info.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009-2014 The Project Lombok Authors.
+ * Copyright (C) 2009-2017 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
@@ -29,6 +29,6 @@
* <li>{@code lombok.experimental} – This package contains lombok features that are new or likely to change before committing to long-term support.
* </ul>
*
- * @see <a href="https://projectlombok.org/features/index.html">Lombok features</a>
+ * @see <a href="https://projectlombok.org/features/all">Lombok features</a>
*/
package lombok;
diff --git a/src/core/lombok/val.java b/src/core/lombok/val.java
index a398fd34..a69d514c 100644
--- a/src/core/lombok/val.java
+++ b/src/core/lombok/val.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010-2013 The Project Lombok Authors.
+ * Copyright (C) 2010-2017 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
@@ -28,7 +28,7 @@ package lombok;
* <p>
* Note that this is an annotation type because {@code val x = 10;} will be desugared to {@code @val final int x = 10;}
* <p>
- * Complete documentation is found at <a href="https://projectlombok.org/features/val.html">the project lombok features page for &#64;val</a>.
+ * Complete documentation is found at <a href="https://projectlombok.org/features/val">the project lombok features page for &#64;val</a>.
*/
public @interface val {
}
diff --git a/src/installer/lombok/installer/InstallerGUI.java b/src/installer/lombok/installer/InstallerGUI.java
index b96fec9c..231e2d3c 100644
--- a/src/installer/lombok/installer/InstallerGUI.java
+++ b/src/installer/lombok/installer/InstallerGUI.java
@@ -171,6 +171,7 @@ public class InstallerGUI {
container.add(buttonBar, constraints);
container.setPreferredSize(new Dimension(INSTALLER_WINDOW_WIDTH, 415));
+ container.setMinimumSize(new Dimension(INSTALLER_WINDOW_WIDTH, 415));
return container;
}
@@ -195,6 +196,7 @@ public class InstallerGUI {
JLabel title;
container.add(title = new JLabel(SUCCESS_TITLE), constraints);
title.setPreferredSize(new Dimension(INSTALLER_WINDOW_WIDTH - 82, 20));
+ title.setMinimumSize(new Dimension(INSTALLER_WINDOW_WIDTH - 82, 20));
constraints.gridy = 1;
constraints.insets = new Insets(8, 0, 0, 16);
@@ -296,6 +298,7 @@ public class InstallerGUI {
container.add(buttonBar, constraints);
container.setPreferredSize(new Dimension(INSTALLER_WINDOW_WIDTH, 415));
+ container.setMinimumSize(new Dimension(INSTALLER_WINDOW_WIDTH, 415));
return container;
}
@@ -319,6 +322,7 @@ public class InstallerGUI {
constraints.gridy = 2;
container.add(example, constraints);
container.setPreferredSize(new Dimension(INSTALLER_WINDOW_WIDTH, 105));
+ container.setMinimumSize(new Dimension(INSTALLER_WINDOW_WIDTH, 105));
return container;
}
@@ -507,6 +511,7 @@ public class InstallerGUI {
container.add(uninstallPlaceholder, constraints);
container.setPreferredSize(new Dimension(INSTALLER_WINDOW_WIDTH, 296));
+ container.setMinimumSize(new Dimension(INSTALLER_WINDOW_WIDTH, 296));
return container;
}
diff --git a/src/utils/lombok/javac/TreeMirrorMaker.java b/src/utils/lombok/javac/TreeMirrorMaker.java
index 918a3242..8cd8cffe 100644
--- a/src/utils/lombok/javac/TreeMirrorMaker.java
+++ b/src/utils/lombok/javac/TreeMirrorMaker.java
@@ -90,12 +90,13 @@ public class TreeMirrorMaker extends TreeCopier<Void> {
return Collections.unmodifiableMap(originalToCopy);
}
- // Monitor issue 205 and issue 694 when making changes here.
+ // Monitor the following issues when making changes here.
+ // - https://github.com/rzwitserloot/lombok/issues/278
+ // - https://github.com/rzwitserloot/lombok/issues/729
@Override public JCTree visitVariable(VariableTree node, Void p) {
JCVariableDecl original = node instanceof JCVariableDecl ? (JCVariableDecl) node : null;
JCVariableDecl copy = (JCVariableDecl) super.visitVariable(node, p);
if (original == null) return copy;
-
copy.sym = original.sym;
if (copy.sym != null) copy.type = original.type;
if (copy.type != null) {
@@ -114,7 +115,7 @@ public class TreeMirrorMaker extends TreeCopier<Void> {
return copy;
}
- // Fix for NPE in HandleVal. See http://code.google.com/p/projectlombok/issues/detail?id=299
+ // Fix for NPE in HandleVal. See https://github.com/rzwitserloot/lombok/issues/372
// This and visitVariable is rather hacky but we're working around evident bugs or at least inconsistencies in javac.
@Override public JCTree visitLabeledStatement(LabeledStatementTree node, Void p) {
return node.getStatement().accept(this, p);
diff --git a/src/website/log4j.properties b/src/website/log4j.properties
new file mode 100644
index 00000000..9cafcc3b
--- /dev/null
+++ b/src/website/log4j.properties
@@ -0,0 +1,6 @@
+log4j.rootLogger=INFO, stdout
+
+log4j.appender.stdout=org.apache.log4j.ConsoleAppender
+log4j.appender.stdout.Target=System.out
+log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
+log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n
diff --git a/src/website/lombok/website/CompileChangelog.java b/src/website/lombok/website/CompileChangelog.java
new file mode 100644
index 00000000..b1ef53c0
--- /dev/null
+++ b/src/website/lombok/website/CompileChangelog.java
@@ -0,0 +1,114 @@
+package lombok.website;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import com.petebevin.markdown.MarkdownProcessor;
+
+public class CompileChangelog {
+ public static void main(String[] args) {
+ String fileIn = args[0];
+ String fileOut = args[1];
+ boolean edge = args.length > 3 && "-edge".equals(args[2]);
+ boolean latest = args.length > 3 && "-latest".equals(args[2]);
+ String version = args.length > 3 ? args[3] : null;
+
+ try {
+ FileInputStream in = new FileInputStream(fileIn);
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+
+ byte[] b = new byte[65536];
+ while (true) {
+ int r = in.read(b);
+ if ( r == -1 ) break;
+ out.write(b, 0, r);
+ }
+ in.close();
+ String markdown = new String(out.toByteArray(), "UTF-8");
+
+ String result;
+ if (edge) {
+ result = buildEdge(sectionByVersion(markdown, version));
+ } else if (latest) {
+ result = buildLatest(sectionByVersion(markdown, version));
+ } else {
+ result = markdownToHtml(markdown);
+ }
+
+ FileOutputStream file = new FileOutputStream(fileOut);
+ file.write(result.getBytes("UTF-8"));
+ file.close();
+ System.exit(0);
+ } catch (Throwable e) {
+ e.printStackTrace();
+ System.exit(1);
+ }
+ }
+
+ public static String getHtmlForEdge(File root, String edgeVersion) throws IOException {
+ File f = new File(root, "doc/changelog.markdown");
+ String raw = readFile(f);
+ return buildEdge(sectionByVersion(raw, edgeVersion));
+ }
+
+ public static String getHtmlForLatest(File root, String latestVersion) throws IOException {
+ File f = new File(root, "doc/changelog.markdown");
+ String raw = readFile(f);
+ return buildLatest(sectionByVersion(raw, latestVersion));
+ }
+
+ public static String getHtml(File root) throws IOException {
+ File f = new File(root, "doc/changelog.markdown");
+ String raw = readFile(f);
+ return markdownToHtml(raw);
+ }
+
+ private static String readFile(File f) throws IOException {
+ byte[] b = new byte[65536];
+ FileInputStream in = new FileInputStream(f);
+ try {
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ while (true) {
+ int r = in.read(b);
+ if ( r == -1 ) break;
+ out.write(b, 0, r);
+ }
+ in.close();
+ return new String(out.toByteArray(), "UTF-8");
+ } finally {
+ in.close();
+ }
+ }
+
+ private static String markdownToHtml(String markdown) {
+ return new MarkdownProcessor().markdown(markdown);
+ }
+
+ private static String buildEdge(String section) {
+ String latest = section != null ? section : "* No changelog records for this edge release.";
+ return markdownToHtml(latest);
+ }
+
+ private static String buildLatest(String section) {
+ String latest = section != null ? section : "* No changelog records for this release.";
+ String noIssueLinks = latest.replaceAll("\\[[^]]*[Ii]ssue[^]]*\\]\\([^)]*\\)", "");
+ String noLinks = noIssueLinks.replaceAll("\\[([^]]*)\\]\\([^)]*\\)", "$1");
+ return markdownToHtml(noLinks);
+ }
+
+ private static String sectionByVersion(String markdown, String version) {
+ if (version.toUpperCase().endsWith("-HEAD") || version.toUpperCase().endsWith("-EDGE")) {
+ version = version.substring(0, version.length() - 5);
+ }
+
+ Pattern p = Pattern.compile(
+ "(?is-m)^.*###\\s*v" + version + ".*?\n(.*?)(?:###\\s*v.*)?$");
+ Matcher m = p.matcher(markdown);
+ return m.matches() ? m.group(1) : null;
+ }
+} \ No newline at end of file
diff --git a/src/website/lombok/website/WebsiteMaker.java b/src/website/lombok/website/WebsiteMaker.java
new file mode 100644
index 00000000..6e773346
--- /dev/null
+++ b/src/website/lombok/website/WebsiteMaker.java
@@ -0,0 +1,403 @@
+package lombok.website;
+
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStreamWriter;
+import java.io.Writer;
+import java.lang.reflect.Method;
+import java.net.URL;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.GregorianCalendar;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.TimeZone;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import de.java2html.Java2Html;
+import freemarker.cache.FileTemplateLoader;
+import freemarker.cache.TemplateLoader;
+import freemarker.core.HTMLOutputFormat;
+import freemarker.template.Configuration;
+import freemarker.template.Template;
+import freemarker.template.TemplateExceptionHandler;
+
+public class WebsiteMaker {
+ private final String version, fullVersion;
+ private final File baseDir, outputDir;
+
+ public WebsiteMaker(String version, String fullVersion, File baseDir, File outputDir) {
+ this.version = version;
+ this.fullVersion = fullVersion;
+ this.baseDir = baseDir;
+ this.outputDir = outputDir;
+ }
+
+ private static final class VersionFinder {
+ public static String getVersion() {
+ return getVersion0("getVersion");
+ }
+
+ public static String getFullVersion() {
+ return getVersion0("getFullVersion");
+ }
+
+ private static String getVersion0(String mName) {
+ try {
+ Class<?> c = Class.forName("lombok.core.Version");
+ Method m = c.getMethod(mName);
+ return (String) m.invoke(null);
+ } catch (ClassNotFoundException e) {
+ System.err.println("You need to specify the version string, and the full version string, as first 2 arguments.");
+ System.exit(1);
+ return null;
+ } catch (Exception e) {
+ if (e instanceof RuntimeException) throw (RuntimeException) e;
+ throw new RuntimeException(e);
+ }
+ }
+ }
+
+ private static void buildAll(String version, String fullVersion, String argIn, String argOut) throws Exception {
+ File in, out;
+ if (argIn == null) {
+ in = new File(".");
+ if (new File(in, "build.xml").isFile() && new File(in, "website").isDirectory()) in = new File(in, "website");
+ } else {
+ in = new File(argIn);
+ }
+
+ if (argOut == null) {
+ if (new File("./build.xml").isFile() && new File("./website").isDirectory() && new File("./build").isDirectory()) {
+ out = new File("./build/website");
+ } else {
+ out = new File(in, "output");
+ }
+ } else {
+ out = new File(argOut);
+ }
+ WebsiteMaker maker = new WebsiteMaker(version, fullVersion, in, out);
+ maker.buildWebsite();
+ }
+
+ private static void buildChangelog(String version, String fullVersion, String argIn, String argOut) throws Exception {
+ File in, out;
+ if (argIn == null) {
+ in = new File(".");
+ if (new File(in, "build.xml").isFile() && new File(in, "website").isDirectory()) in = new File(in, "website");
+ } else {
+ in = new File(argIn);
+ }
+
+ if (argOut == null) {
+ if (new File("./build.xml").isFile() && new File("./website").isDirectory() && new File("./build").isDirectory()) {
+ out = new File("./build/website/changelog.html");
+ } else {
+ out = new File(in, "output/changelog.html");
+ }
+ } else {
+ out = new File(argOut);
+ }
+ WebsiteMaker maker = new WebsiteMaker(version, fullVersion, in, out.getParentFile());
+ maker.buildChangelog(out);
+ }
+
+ private static void buildDownloadEdge(String version, String fullVersion, String argIn, String argOut) throws Exception {
+ File in, out;
+ if (argIn == null) {
+ in = new File(".");
+ if (new File(in, "build.xml").isFile() && new File(in, "website").isDirectory()) in = new File(in, "website");
+ } else {
+ in = new File(argIn);
+ }
+
+ if (argOut == null) {
+ if (new File("./build.xml").isFile() && new File("./website").isDirectory() && new File("./build").isDirectory()) {
+ out = new File("./build/website-edge/download-edge.html");
+ } else {
+ out = new File(in, "output/download-edge.html");
+ }
+ } else {
+ out = new File(argOut);
+ }
+ WebsiteMaker maker = new WebsiteMaker(version, fullVersion, in, out.getParentFile());
+ maker.buildDownloadEdge(out);
+ }
+
+ private static void buildChangelogLatest(String version, String fullVersion, String argIn, String argOut) throws Exception {
+ File in, out;
+ if (argIn == null) {
+ in = new File(".");
+ if (new File(in, "build.xml").isFile() && new File(in, "website").isDirectory()) in = new File(in, "website");
+ } else {
+ in = new File(argIn);
+ }
+
+ if (argOut == null) {
+ if (new File("./build.xml").isFile() && new File("./website").isDirectory() && new File("./build").isDirectory()) {
+ out = new File("./build/latestchanges.html");
+ } else {
+ out = new File(in, "output/latestchanges.html");
+ }
+ } else {
+ out = new File(argOut);
+ }
+ WebsiteMaker maker = new WebsiteMaker(version, fullVersion, in, out.getParentFile());
+ maker.buildChangelogLatest(out);
+ }
+
+ public static void main(String[] args) throws Exception {
+ String version, fullVersion;
+
+ if (args.length < 2) {
+ version = VersionFinder.getVersion();
+ fullVersion = VersionFinder.getFullVersion();
+ } else {
+ version = args[0];
+ fullVersion = args[1];
+ }
+
+ if (args.length < 3 || args[2].equalsIgnoreCase("all")) {
+ buildAll(version, fullVersion, args.length < 4 ? null : args[3], args.length < 5 ? null : args[4]);
+ } else if (args[2].equalsIgnoreCase("changelog")) {
+ buildChangelog(version, fullVersion, args.length < 4 ? null : args[3], args.length < 5 ? null : args[4]);
+ } else if (args[2].equalsIgnoreCase("download-edge")) {
+ buildDownloadEdge(version, fullVersion, args.length < 4 ? null : args[3], args.length < 5 ? null : args[4]);
+ } else if (args[2].equalsIgnoreCase("changelog-latest")) {
+ buildChangelogLatest(version, fullVersion, args.length < 4 ? null : args[3], args.length < 5 ? null : args[4]);
+ } else {
+ throw new IllegalArgumentException("3rd argument must be one of 'all', 'changelog', 'download-edge', 'changelog-latest'");
+ }
+ }
+
+ private Configuration makeFreemarkerConfig() throws IOException {
+ Configuration freemarkerConfig = new Configuration(Configuration.VERSION_2_3_25);
+ freemarkerConfig.setEncoding(Locale.ENGLISH, "UTF-8");
+ freemarkerConfig.setOutputEncoding("UTF-8");
+ freemarkerConfig.setOutputFormat(HTMLOutputFormat.INSTANCE);
+ freemarkerConfig.setTemplateLoader(createLoader());
+ freemarkerConfig.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);
+ return freemarkerConfig;
+ }
+
+ public void buildChangelog(File out) throws Exception {
+ Configuration freemarkerConfig = makeFreemarkerConfig();
+ outputDir.mkdirs();
+ convertChangelog(freemarkerConfig, out);
+ }
+
+ public void buildChangelogLatest(File out) throws Exception {
+ outputDir.mkdirs();
+ String htmlForLatest = CompileChangelog.getHtmlForLatest(baseDir.getParentFile(), version);
+ FileOutputStream fos = new FileOutputStream(out);
+ try {
+ BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(fos, "UTF-8"));
+ bw.write(htmlForLatest);
+ bw.close();
+ } finally {
+ fos.close();
+ }
+ }
+
+ public void buildDownloadEdge(File out) throws Exception {
+ Configuration freemarkerConfig = makeFreemarkerConfig();
+
+ outputDir.mkdirs();
+ convertDownloadEdge(freemarkerConfig, out);
+ }
+
+ public void buildHtAccess(File out) throws Exception {
+ Configuration freemarkerConfig = new Configuration(Configuration.VERSION_2_3_25);
+ freemarkerConfig.setEncoding(Locale.ENGLISH, "UTF-8");
+ freemarkerConfig.setOutputEncoding("UTF-8");
+ freemarkerConfig.setOutputFormat(HTMLOutputFormat.INSTANCE);
+ freemarkerConfig.setTemplateLoader(createLoader("extra"));
+ freemarkerConfig.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);
+
+ outputDir.mkdirs();
+ convertHtAccess(freemarkerConfig, out);
+ }
+
+ public void buildWebsite() throws Exception {
+ Configuration freemarkerConfig = makeFreemarkerConfig();
+
+ outputDir.mkdirs();
+ convertTemplates(freemarkerConfig);
+ buildHtAccess(new File(outputDir, ".htaccess"));
+ }
+
+ private TemplateLoader createLoader() throws IOException {
+ return createLoader("templates");
+ }
+
+ private TemplateLoader createLoader(String base) throws IOException {
+ return new FileTemplateLoader(new File(baseDir, base));
+ }
+
+ private void convertHtAccess(Configuration freemarker, File outFile) throws Exception {
+ Map<String, Object> dataModel = new HashMap<String, Object>();
+ dataModel.put("setupPages", listHtmlNames(new File(outputDir, "setup")));
+ dataModel.put("featurePages", listHtmlNames(new File(outputDir, "features")));
+ dataModel.put("experimentalPages", listHtmlNames(new File(outputDir, "features/experimental")));
+ Template template = freemarker.getTemplate("htaccess");
+ FileOutputStream fileOut = new FileOutputStream(outFile);
+ try {
+ Writer wr = new BufferedWriter(new OutputStreamWriter(fileOut, "UTF-8"));
+ template.process(dataModel, wr);
+ wr.close();
+ } finally {
+ fileOut.close();
+ }
+ }
+
+ private List<String> listHtmlNames(File dir) {
+ List<String> out = new ArrayList<String>();
+ for (String s : dir.list()) {
+ if (s.endsWith(".html") && !s.equals("index.html")) out.add(s.substring(0, s.length() - 5));
+ }
+ return out;
+ }
+
+ private void convertChangelog(Configuration freemarker, File outFile) throws Exception {
+ Map<String, Object> dataModel = createBasicDataModel();
+
+ Template template = freemarker.getTemplate("changelog.html");
+ FileOutputStream fileOut = new FileOutputStream(outFile);
+ try {
+ Writer wr = new BufferedWriter(new OutputStreamWriter(fileOut, "UTF-8"));
+ template.process(dataModel, wr);
+ wr.close();
+ } finally {
+ fileOut.close();
+ }
+ }
+
+ private void convertDownloadEdge(Configuration freemarker, File outFile) throws Exception {
+ Map<String, Object> dataModel = createBasicDataModel();
+
+ Template template = freemarker.getTemplate("_download-edge.html");
+ FileOutputStream fileOut = new FileOutputStream(outFile);
+ try {
+ Writer wr = new BufferedWriter(new OutputStreamWriter(fileOut, "UTF-8"));
+ template.process(dataModel, wr);
+ wr.close();
+ } finally {
+ fileOut.close();
+ }
+ }
+
+ private void convertTemplates(Configuration freemarker) throws Exception {
+ File basePagesLoc = new File(baseDir, "templates");
+ Map<String, Object> dataModel = createBasicDataModel();
+ dataModel.putAll(createExtendedDataModel());
+ convertTemplates_(freemarker, "", basePagesLoc, outputDir, 0, dataModel);
+ }
+
+ private void convertTemplates_(Configuration freemarker, String prefix, File from, File to, int depth, Map<String, Object> dataModel) throws Exception {
+ if (depth > 50) throw new IllegalArgumentException("50 levels is too deep: " + from);
+
+ for (File f : from.listFiles()) {
+ if (f.isDirectory()) convertTemplates_(freemarker, prefix + f.getName() + "/", f, new File(to, f.getName()), depth + 1, dataModel);
+ if (!f.isFile() || !f.getName().endsWith(".html") || f.getName().startsWith("_")) continue;
+ to.mkdirs();
+ Template template = freemarker.getTemplate(prefix + f.getName());
+ FileOutputStream fileOut = new FileOutputStream(new File(to, f.getName()));
+ try {
+ Writer wr = new BufferedWriter(new OutputStreamWriter(fileOut, "UTF-8"));
+ template.process(dataModel, wr);
+ wr.close();
+ } finally {
+ fileOut.close();
+ }
+ }
+ }
+
+ private Map<String, Object> createBasicDataModel() throws IOException {
+ Map<String, Object> data = new HashMap<String, Object>();
+
+ SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss 'UTC'");
+ sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
+ String currentTime = sdf.format(new Date());
+
+ data.put("version", version);
+ data.put("fullVersion", fullVersion);
+ data.put("timestampString", currentTime);
+ data.put("year", "" + new GregorianCalendar().get(Calendar.YEAR));
+ data.put("changelog", CompileChangelog.getHtml(baseDir.getParentFile()));
+ data.put("changelogEdge", CompileChangelog.getHtmlForEdge(baseDir.getParentFile(), version));
+
+ return data;
+ }
+
+ private static final Pattern LOMBOK_LINK = Pattern.compile("^.*<a(?: (?:id|class|rel|rev|download|target|type)(?:=\"[^\"]*\")?)* href=\"(downloads/[^\"]+)\"(?: (?:id|class|rel|rev|download|target|type)(?:=\"[^\"]*\")?)*>([^<]+)</a>.*$");
+ private Map<String, Object> createExtendedDataModel() throws IOException {
+ Map<String, Object> data = new HashMap<String, Object>();
+
+ data.put("usages", new HtmlMaker(new File(baseDir, "usageExamples")));
+ InputStream in = new URL("https://projectlombok.org/all-versions.html").openStream();
+ ArrayList<List<String>> links = new ArrayList<List<String>>();
+ try {
+ BufferedReader br = new BufferedReader(new InputStreamReader(in, "UTF-8"));
+ for (String line = br.readLine(); line != null; line = br.readLine()) {
+ Matcher m = LOMBOK_LINK.matcher(line);
+ if (m.matches()) links.add(Arrays.asList(m.group(1), m.group(2)));
+ }
+ } finally {
+ in.close();
+ }
+
+ data.put("linksToVersions", links);
+
+ return data;
+ }
+
+ public static class HtmlMaker {
+ private final File usagesDir;
+
+ HtmlMaker(File usagesDir) {
+ this.usagesDir = usagesDir;
+ }
+
+ public String pre(String name) throws IOException {
+ return convert(new File(usagesDir, name + "Example_pre.jpage"));
+ }
+
+ public String post(String name) throws IOException {
+ return convert(new File(usagesDir, name + "Example_post.jpage"));
+ }
+
+ public String convert(File file) throws IOException {
+ String rawJava = readFully(file);
+ return Java2Html.convertToHtml(rawJava);
+ }
+ }
+
+ public static String readFully(File file) throws IOException {
+ FileInputStream fis = new FileInputStream(file);
+ try {
+ InputStreamReader isr = new InputStreamReader(fis, "UTF-8");
+ StringBuilder out = new StringBuilder();
+ char[] b = new char[65536];
+ while (true) {
+ int r = isr.read(b);
+ if (r == -1) break;
+ out.append(b, 0, r);
+ }
+ return out.toString();
+ } finally {
+ fis.close();
+ }
+ }
+}