From cb9b907839aa0c72ffa41f8a13bfab5cb1341258 Mon Sep 17 00:00:00 2001 From: Reinier Zwitserloot Date: Tue, 12 Mar 2013 01:29:15 +0100 Subject: In delombok, we mark the AST as changed if we remove an annotation; this fixes the issue where delombok would leave lombok annotations in the file if that annotation had no actual effect (such as @Getter on a field if there is an explicit getX method for that field). issue #443: delombok would screw up @SneakyThrows on methods or constructors with empty bodies. Now we generate warnings for this. --- website/features/SneakyThrows.html | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'website/features/SneakyThrows.html') diff --git a/website/features/SneakyThrows.html b/website/features/SneakyThrows.html index 0f04b7d9..808a7879 100644 --- a/website/features/SneakyThrows.html +++ b/website/features/SneakyThrows.html @@ -64,7 +64,11 @@ statement in a try/catch block with just e.printStackTrace() in the catch block. This is so spectacularly non-productive compared to just sneakily throwing the exception onwards, that Roel and Reinier feel more than justified in claiming that the checked exception system is far from perfect, and thus an opt-out mechanism is warranted. -

+

+ If you put @SneakyThrows on a constructor, any call to a sibling or super constructor is excluded from the @SneakyThrows treatment. This is a + java restriction we cannot work around: Calls to sibling/super constructors MUST be the first statement in the constructor; they cannot be placed inside try/catch blocks. +

+ @SneakyThrows on an empty method, or a constructor that is empty or only has a call to a sibling / super constructor results in no try/catch block and a warning.

diff --git a/website/features/Data.html b/website/features/Data.html index 8ace96cb..1c8510b7 100644 --- a/website/features/Data.html +++ b/website/features/Data.html @@ -75,7 +75,7 @@
diff --git a/website/features/Delegate.html b/website/features/Delegate.html index 532f3f54..02cdf290 100644 --- a/website/features/Delegate.html +++ b/website/features/Delegate.html @@ -55,16 +55,15 @@ When passing classes to the annotation's types or excludes parameter, you cannot include generics. This is a limitation of java. Use private inner interfaces or classes that extend the intended type including the generics parameter to work around this problem. -

-

+

When passing classes to the annotation, these classes do not need to be supertypes of the field. See the example. -

-

+

@Delegate cannot be used on static fields or methods. -

+

+
diff --git a/website/features/GetterLazy.html b/website/features/GetterLazy.html index bc5ecb0c..f70c8e78 100644 --- a/website/features/GetterLazy.html +++ b/website/features/GetterLazy.html @@ -46,7 +46,7 @@
diff --git a/website/features/GetterSetter.html b/website/features/GetterSetter.html index 03704119..c78b03bd 100644 --- a/website/features/GetterSetter.html +++ b/website/features/GetterSetter.html @@ -75,7 +75,7 @@
diff --git a/website/features/Log.html b/website/features/Log.html index 2fb91956..2d4fa375 100644 --- a/website/features/Log.html +++ b/website/features/Log.html @@ -60,7 +60,7 @@
diff --git a/website/features/NonNull.html b/website/features/NonNull.html new file mode 100644 index 00000000..9faad502 --- /dev/null +++ b/website/features/NonNull.html @@ -0,0 +1,73 @@ + + + + + + + + val +
+
+
+ +

@NonNull

+ +
+

Overview

+

+ NEW in Lombok 0.11.10: You can use @NonNull on the parameter of a method or constructor to have lombok generate a null-check statement for you. +

+ Lombok has always treated any annotation named @NonNull on a field as a signal to generate a null-check if lombok generates an entire method or constructor for you, via + for example @Data. Now, however, using lombok's own @lombok.NonNull on a parameter results in the insertion of just the null-check + statement inside your own method or constructor. +

+ The null-check looks like if (param == null) throw new NullPointerException("param"); and will be inserted at the very top of your method. For constructors, the null-check + will be inserted immediately following any explicit this() or super() calls. +

+ If a null-check is already present at the top, no additional null-check will be generated. +

+
+
+
+

With Lombok

+
@HTML_PRE@
+
+
+
+

Vanilla Java

+
@HTML_POST@
+
+
+
+
+

Small print

+

+ Lombok's detection scheme for already existing null-checks consists of scanning for if statements that look just like lombok's own. Any 'throws' statement as + the 'then' part of the if statement, whether in braces or not, counts. The conditional of the if statement must look exactly like PARAMNAME == null. + The first statement in your method that is not such a null-check stops the process of inspecting for null-checks. +

+ While @Data and other method-generating lombok annotations will trigger on any annotation named @NonNull regardless of casing or package name, + this feature only triggers on lombok's own @NonNull annotation from the lombok package. +

+ A @NonNull on a primitive parameter results in a warning. No null-check will be generated. +

+
+
+ +
+
+
+ + + diff --git a/website/features/SneakyThrows.html b/website/features/SneakyThrows.html index 808a7879..573bd95c 100644 --- a/website/features/SneakyThrows.html +++ b/website/features/SneakyThrows.html @@ -54,8 +54,6 @@

Small print

- @SneakyThrows is an implementation of this feature request: http://bugs.sun.com/view_bug.do?bug_id=6534270. -

Because @SneakyThrows is an implementation detail and not part of your method signature, it is an error if you try to declare a checked exception as sneakily thrown when you don't call any methods that throw this exception. (Doing so is perfectly legal for throws statements to accommodate subclasses). Similarly, @SneakyThrows does not inherit. @@ -72,7 +70,7 @@

diff --git a/website/features/Synchronized.html b/website/features/Synchronized.html index 4b6ef251..9ab6c87f 100644 --- a/website/features/Synchronized.html +++ b/website/features/Synchronized.html @@ -59,7 +59,7 @@
diff --git a/website/features/ToString.html b/website/features/ToString.html index c3b389ba..585dc72b 100644 --- a/website/features/ToString.html +++ b/website/features/ToString.html @@ -68,7 +68,7 @@
diff --git a/website/features/index.html b/website/features/index.html index 9751a37d..8b3765c1 100644 --- a/website/features/index.html +++ b/website/features/index.html @@ -13,10 +13,14 @@

Lombok features

+
val
+
Finally! Hassle-free final local variables.
+
@NonNull
+
or: How I learned to stop worrying and love the NullPointerException.
+
@Cleanup
+
Automatic resource management: Call your close() methods safely with no hassle.
@Getter / @Setter
Never write public int getFoo() {return foo;} again.
-
@Getter(lazy=true)
-
Laziness is a virtue!
@ToString
No need to start a debugger to see your fields: Just let lombok generate a toString for you!
@EqualsAndHashCode
@@ -26,16 +30,14 @@
@Data
All together now: A shortcut for @ToString, @EqualsAndHashCode, @Getter on all fields, and @Setter on all non-final fields, and @RequiredArgsConstructor!
-
@Cleanup
-
Automatic resource management: Call your close() methods safely with no hassle.
-
@Synchronized
-
synchronized done right: Don't expose your locks.
@SneakyThrows
To boldly throw checked exceptions where no one has thrown them before!
+
@Synchronized
+
synchronized done right: Don't expose your locks.
+
@Getter(lazy=true)
+
Laziness is a virtue!
@Log
Captain's Log, stardate 24435.7: "What was that line again?"
-
val
-
Finally! Hassle-free final local variables.
@Delegate
Don't lose your composition.
experimental features
diff --git a/website/features/val.html b/website/features/val.html index cec799e9..c4c8ad27 100644 --- a/website/features/val.html +++ b/website/features/val.html @@ -50,7 +50,7 @@
-- cgit From b5747963c022f680168ff66ebdc7860adb954882 Mon Sep 17 00:00:00 2001 From: Reinier Zwitserloot Date: Tue, 25 Jun 2013 00:23:02 +0200 Subject: Value has been promoted to the main package. --- doc/changelog.markdown | 2 +- src/core/lombok/Data.java | 4 +- src/core/lombok/Value.java | 58 ++++++++++++++++ src/core/lombok/core/LombokInternalAliasing.java | 52 ++++++++++++++ src/core/lombok/core/TypeLibrary.java | 6 ++ src/core/lombok/core/TypeResolver.java | 9 +-- src/core/lombok/eclipse/EclipseImportList.java | 13 ++-- src/core/lombok/eclipse/handlers/HandleValue.java | 2 +- src/core/lombok/javac/JavacImportList.java | 9 ++- src/core/lombok/javac/handlers/HandleValue.java | 4 +- .../lombok/javac/handlers/JavacHandlerUtil.java | 19 ++++- src/delombok/lombok/delombok/DelombokApp.java | 1 + .../resource/after-delombok/ValueExperimental.java | 46 ++++++++++++ .../ValueExperimentalStarImport.java | 25 +++++++ .../resource/after-ecj/ValueExperimental.java | 39 +++++++++++ .../after-ecj/ValueExperimentalStarImport.java | 20 ++++++ test/transform/resource/after-ecj/ValuePlain.java | 4 +- .../resource/before/ValueExperimental.java | 9 +++ .../before/ValueExperimentalStarImport.java | 5 ++ test/transform/resource/before/ValuePlain.java | 4 +- website/features/Data.html | 2 +- website/features/SneakyThrows.html | 2 +- website/features/Value.html | 76 ++++++++++++++++++++ website/features/experimental/Value.html | 81 ---------------------- website/features/experimental/Wither.html | 2 +- website/features/experimental/index.html | 9 ++- website/features/experimental/onX.html | 2 +- website/features/index.html | 2 + 28 files changed, 396 insertions(+), 111 deletions(-) create mode 100644 src/core/lombok/Value.java create mode 100644 src/core/lombok/core/LombokInternalAliasing.java create mode 100644 test/transform/resource/after-delombok/ValueExperimental.java create mode 100644 test/transform/resource/after-delombok/ValueExperimentalStarImport.java create mode 100644 test/transform/resource/after-ecj/ValueExperimental.java create mode 100644 test/transform/resource/after-ecj/ValueExperimentalStarImport.java create mode 100644 test/transform/resource/before/ValueExperimental.java create mode 100644 test/transform/resource/before/ValueExperimentalStarImport.java create mode 100644 website/features/Value.html delete mode 100644 website/features/experimental/Value.html (limited to 'website/features/SneakyThrows.html') diff --git a/doc/changelog.markdown b/doc/changelog.markdown index 85fcd86a..95ee5764 100644 --- a/doc/changelog.markdown +++ b/doc/changelog.markdown @@ -2,7 +2,7 @@ Lombok Changelog ---------------- ### v0.11.9 (Edgy Guinea Pig) -* FEATURE: {Experimental} `@Builder` support. One of our earliest feature request issues has finally been addressed. [@Builder documentation](http://projectlombok.org/features/experimental/Builder.html). +* FEATURE: {Experimental} `@Builder` support. One of our earliest feature request issues, [Issue #16](https://code.google.com/p/projectlombok/issues/detail?id=16), has finally been addressed. [@Builder documentation](http://projectlombok.org/features/experimental/Builder.html). * FEATURE: `@NonNull` on a method or constructor parameter now generates a null-check statement at the start of your method. This nullcheck will throw a `NullPointerException` with the name of the parameter as the message. [Issue #514](https://code.google.com/p/projectlombok/issues/detail?id=514) * BUGFIX: Usage of `Lombok.sneakyThrow()` or `@SneakyThrows` would sometimes result in invalid classes (classes which fail with `VerifyError`). [Issue #470](https://code.google.com/p/projectlombok/issues/detail?id=470) * BUGFIX: Using `val` in try-with-resources did not work for javac. [Issue #520](https://code.google.com/p/projectlombok/issues/detail?id=520) diff --git a/src/core/lombok/Data.java b/src/core/lombok/Data.java index ee6f2fcb..bbc8d920 100644 --- a/src/core/lombok/Data.java +++ b/src/core/lombok/Data.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009-2012 The Project Lombok Authors. + * Copyright (C) 2009-2013 The Project Lombok Authors. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -39,7 +39,7 @@ import java.lang.annotation.Target; * @see RequiredArgsConstructor * @see ToString * @see EqualsAndHashCode - * @see lombok.experimental.Value + * @see lombok.Value */ @Target(ElementType.TYPE) @Retention(RetentionPolicy.SOURCE) diff --git a/src/core/lombok/Value.java b/src/core/lombok/Value.java new file mode 100644 index 00000000..2cffe15b --- /dev/null +++ b/src/core/lombok/Value.java @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2012-2013 The Project Lombok Authors. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package lombok; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Generates a lot of code which fits with a class that is a representation of an immutable entity. + *

+ * Equivalent to {@code @Getter @FieldDefaults(makeFinal=true, level=AccessLevel.PRIVATE) @RequiredArgsConstructor @ToString @EqualsAndHashCode}. + *

+ * Complete documentation is found at the project lombok features page for @Value. + * + * @see lombok.Getter + * @see lombok.experimental.FieldDefaults + * @see lombok.RequiredArgsConstructor + * @see lombok.ToString + * @see lombok.EqualsAndHashCode + * @see lombok.Data + */ +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.SOURCE) +public @interface Value { + /** + * If you specify a static constructor name, then the generated constructor will be private, and + * instead a static factory method is created that other classes can use to create instances. + * We suggest the name: "of", like so: + * + *

+	 *     public @Data(staticConstructor = "of") class Point { final int x, y; }
+	 * 
+ * + * Default: No static constructor, instead the normal constructor is public. + */ + String staticConstructor() default ""; +} diff --git a/src/core/lombok/core/LombokInternalAliasing.java b/src/core/lombok/core/LombokInternalAliasing.java new file mode 100644 index 00000000..4fd7b29d --- /dev/null +++ b/src/core/lombok/core/LombokInternalAliasing.java @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2013 The Project Lombok Authors. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package lombok.core; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +public class LombokInternalAliasing { + public static final Map IMPLIED_EXTRA_STAR_IMPORTS; + public static final Map ALIASES; + + /** + * Provide a fully qualified name (FQN), and the canonical version of this is returned. + */ + public static String processAliases(String in) { + if (in == null) return null; + for (Map.Entry e : ALIASES.entrySet()) { + if (in.equals(e.getKey())) return e.getValue(); + } + return in; + } + + static { + Map m = new HashMap(); + m.put("lombok.experimental", "lombok"); + IMPLIED_EXTRA_STAR_IMPORTS = Collections.unmodifiableMap(m); + + m = new HashMap(); + m.put("lombok.experimental.Value", "lombok.Value"); + ALIASES = Collections.unmodifiableMap(m); + } +} diff --git a/src/core/lombok/core/TypeLibrary.java b/src/core/lombok/core/TypeLibrary.java index a89091c4..c0e9dc43 100644 --- a/src/core/lombok/core/TypeLibrary.java +++ b/src/core/lombok/core/TypeLibrary.java @@ -74,6 +74,9 @@ public class TypeLibrary { unqualifiedToQualifiedMap.put(unqualified, fullyQualifiedTypeName); unqualifiedToQualifiedMap.put(fullyQualifiedTypeName, fullyQualifiedTypeName); + for (Map.Entry e : LombokInternalAliasing.ALIASES.entrySet()) { + if (fullyQualifiedTypeName.equals(e.getValue())) unqualifiedToQualifiedMap.put(e.getKey(), fullyQualifiedTypeName); + } } /** @@ -85,6 +88,9 @@ public class TypeLibrary { public String toQualified(String typeReference) { if (unqualifiedToQualifiedMap == null) { if (typeReference.equals(unqualified) || typeReference.equals(qualified)) return qualified; + for (Map.Entry e : LombokInternalAliasing.ALIASES.entrySet()) { + if (e.getKey().equals(typeReference)) return e.getValue(); + } return null; } return unqualifiedToQualifiedMap.get(typeReference); diff --git a/src/core/lombok/core/TypeResolver.java b/src/core/lombok/core/TypeResolver.java index e2ba03b5..287a085f 100644 --- a/src/core/lombok/core/TypeResolver.java +++ b/src/core/lombok/core/TypeResolver.java @@ -39,19 +39,12 @@ public class TypeResolver { this.imports = importList; } -// private static ImportList makeImportList(String packageString, Collection importStrings) { -// Set imports = new HashSet(); -// if (packageString != null) imports.add(packageString + ".*"); -// imports.addAll(importStrings == null ? Collections.emptySet() : importStrings); -// imports.add("java.lang.*"); -// return imports; -// } -// public boolean typeMatches(LombokNode context, String fqn, String typeRef) { return typeRefToFullyQualifiedName(context, TypeLibrary.createLibraryForSingleType(fqn), typeRef) != null; } public String typeRefToFullyQualifiedName(LombokNode context, TypeLibrary library, String typeRef) { + typeRef = LombokInternalAliasing.processAliases(typeRef); // When asking if 'Foo' could possibly be referring to 'bar.Baz', the answer is obviously no. String qualified = library.toQualified(typeRef); if (qualified == null) return null; diff --git a/src/core/lombok/eclipse/EclipseImportList.java b/src/core/lombok/eclipse/EclipseImportList.java index 264ed91f..69246b3c 100644 --- a/src/core/lombok/eclipse/EclipseImportList.java +++ b/src/core/lombok/eclipse/EclipseImportList.java @@ -21,19 +21,21 @@ */ package lombok.eclipse; -import static lombok.eclipse.Eclipse.*; +import static lombok.eclipse.Eclipse.toQualifiedName; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; +import java.util.Map; + +import lombok.core.ImportList; +import lombok.core.LombokInternalAliasing; import org.eclipse.jdt.internal.compiler.ast.ASTNode; import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration; import org.eclipse.jdt.internal.compiler.ast.ImportReference; -import lombok.core.ImportList; - public class EclipseImportList implements ImportList { private ImportReference[] imports; private ImportReference pkg; @@ -53,13 +55,16 @@ public class EclipseImportList implements ImportList { int len = token.length; if (len != unqualified.length()) continue; for (int i = 0; i < len; i++) if (token[i] != unqualified.charAt(i)) continue outer; - return toQualifiedName(tokens); + return LombokInternalAliasing.processAliases(toQualifiedName(tokens)); } } return null; } @Override public boolean hasStarImport(String packageName) { + for (Map.Entry e : LombokInternalAliasing.IMPLIED_EXTRA_STAR_IMPORTS.entrySet()) { + if (e.getValue().equals(packageName) && hasStarImport(e.getKey())) return true; + } if (isEqual(packageName, pkg)) return true; if ("java.lang".equals(packageName)) return true; if (imports != null) for (ImportReference imp : imports) { diff --git a/src/core/lombok/eclipse/handlers/HandleValue.java b/src/core/lombok/eclipse/handlers/HandleValue.java index 60938649..0607137b 100644 --- a/src/core/lombok/eclipse/handlers/HandleValue.java +++ b/src/core/lombok/eclipse/handlers/HandleValue.java @@ -32,7 +32,7 @@ import lombok.eclipse.EclipseAnnotationHandler; import lombok.eclipse.EclipseNode; import lombok.eclipse.handlers.HandleConstructor.SkipIfConstructorExists; import lombok.experimental.NonFinal; -import lombok.experimental.Value; +import lombok.Value; import org.eclipse.jdt.internal.compiler.ast.Annotation; import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration; diff --git a/src/core/lombok/javac/JavacImportList.java b/src/core/lombok/javac/JavacImportList.java index fbd4a518..d5d7460a 100644 --- a/src/core/lombok/javac/JavacImportList.java +++ b/src/core/lombok/javac/JavacImportList.java @@ -23,6 +23,7 @@ package lombok.javac; import java.util.ArrayList; import java.util.Collection; +import java.util.Map; import com.sun.tools.javac.tree.JCTree; import com.sun.tools.javac.tree.JCTree.JCCompilationUnit; @@ -32,6 +33,7 @@ import com.sun.tools.javac.tree.JCTree.JCImport; import com.sun.tools.javac.util.List; import lombok.core.ImportList; +import lombok.core.LombokInternalAliasing; public class JavacImportList implements ImportList { private final JCExpression pkg; @@ -48,13 +50,18 @@ public class JavacImportList implements ImportList { JCTree qual = ((JCImport) def).qualid; if (!(qual instanceof JCFieldAccess)) continue; String simpleName = ((JCFieldAccess) qual).name.toString(); - if (simpleName.equals(unqualified)) return qual.toString(); + if (simpleName.equals(unqualified)) { + return LombokInternalAliasing.processAliases(qual.toString()); + } } return null; } @Override public boolean hasStarImport(String packageName) { + for (Map.Entry e : LombokInternalAliasing.IMPLIED_EXTRA_STAR_IMPORTS.entrySet()) { + if (e.getValue().equals(packageName) && hasStarImport(e.getKey())) return true; + } if (pkg != null && pkg.toString().equals(packageName)) return true; if ("java.lang".equals(packageName)) return true; diff --git a/src/core/lombok/javac/handlers/HandleValue.java b/src/core/lombok/javac/handlers/HandleValue.java index a59865f7..c0127f3c 100644 --- a/src/core/lombok/javac/handlers/HandleValue.java +++ b/src/core/lombok/javac/handlers/HandleValue.java @@ -26,7 +26,7 @@ import lombok.AccessLevel; import lombok.core.AnnotationValues; import lombok.core.HandlerPriority; import lombok.experimental.NonFinal; -import lombok.experimental.Value; +import lombok.Value; import lombok.javac.JavacAnnotationHandler; import lombok.javac.JavacNode; import lombok.javac.handlers.HandleConstructor.SkipIfConstructorExists; @@ -45,7 +45,7 @@ import com.sun.tools.javac.tree.JCTree.JCModifiers; @HandlerPriority(-512) //-2^9; to ensure @EqualsAndHashCode and such pick up on this handler making the class final and messing with the fields' access levels, run earlier. public class HandleValue extends JavacAnnotationHandler { @Override public void handle(AnnotationValues annotation, JCAnnotation ast, JavacNode annotationNode) { - deleteAnnotationIfNeccessary(annotationNode, Value.class); + deleteAnnotationIfNeccessary(annotationNode, Value.class, lombok.experimental.Value.class); JavacNode typeNode = annotationNode.up(); boolean notAClass = !isClass(typeNode); diff --git a/src/core/lombok/javac/handlers/JavacHandlerUtil.java b/src/core/lombok/javac/handlers/JavacHandlerUtil.java index 92cebf4c..1784be90 100644 --- a/src/core/lombok/javac/handlers/JavacHandlerUtil.java +++ b/src/core/lombok/javac/handlers/JavacHandlerUtil.java @@ -280,7 +280,22 @@ public class JavacHandlerUtil { * then removes any import statement that imports this exact annotation (not star imports). * Only does this if the DeleteLombokAnnotations class is in the context. */ + @SuppressWarnings("unchecked") public static void deleteAnnotationIfNeccessary(JavacNode annotation, Class annotationType) { + deleteAnnotationIfNeccessary0(annotation, annotationType); + } + + /** + * Removes the annotation from javac's AST (it remains in lombok's AST), + * then removes any import statement that imports this exact annotation (not star imports). + * Only does this if the DeleteLombokAnnotations class is in the context. + */ + @SuppressWarnings("unchecked") + public static void deleteAnnotationIfNeccessary(JavacNode annotation, Class annotationType1, Class annotationType2) { + deleteAnnotationIfNeccessary0(annotation, annotationType1, annotationType2); + } + + private static void deleteAnnotationIfNeccessary0(JavacNode annotation, Class... annotationTypes) { if (inNetbeansEditor(annotation)) return; if (!annotation.shouldDeleteLombokAnnotations()) return; JavacNode parentNode = annotation.directUp(); @@ -309,7 +324,9 @@ public class JavacHandlerUtil { } parentNode.getAst().setChanged(); - deleteImportFromCompilationUnit(annotation, annotationType.getName()); + for (Class annotationType : annotationTypes) { + deleteImportFromCompilationUnit(annotation, annotationType.getName()); + } } public static void deleteImportFromCompilationUnit(JavacNode node, String name) { diff --git a/src/delombok/lombok/delombok/DelombokApp.java b/src/delombok/lombok/delombok/DelombokApp.java index 90a7b55e..5b97be08 100644 --- a/src/delombok/lombok/delombok/DelombokApp.java +++ b/src/delombok/lombok/delombok/DelombokApp.java @@ -84,6 +84,7 @@ public class DelombokApp extends LombokApp { return null; } + @SuppressWarnings("resource") final JarFile toolsJarFile = new JarFile(toolsJar); ClassLoader loader = new ClassLoader() { diff --git a/test/transform/resource/after-delombok/ValueExperimental.java b/test/transform/resource/after-delombok/ValueExperimental.java new file mode 100644 index 00000000..77a48ec9 --- /dev/null +++ b/test/transform/resource/after-delombok/ValueExperimental.java @@ -0,0 +1,46 @@ +final class ValueExperimental1 { + @java.lang.SuppressWarnings("all") + public ValueExperimental1() { + } + @java.lang.Override + @java.lang.SuppressWarnings("all") + public boolean equals(final java.lang.Object o) { + if (o == this) return true; + if (!(o instanceof ValueExperimental1)) return false; + return true; + } + @java.lang.Override + @java.lang.SuppressWarnings("all") + public int hashCode() { + int result = 1; + return result; + } + @java.lang.Override + @java.lang.SuppressWarnings("all") + public java.lang.String toString() { + return "ValueExperimental1()"; + } +} +final class ValueExperimental2 { + @java.lang.SuppressWarnings("all") + public ValueExperimental2() { + } + @java.lang.Override + @java.lang.SuppressWarnings("all") + public boolean equals(final java.lang.Object o) { + if (o == this) return true; + if (!(o instanceof ValueExperimental2)) return false; + return true; + } + @java.lang.Override + @java.lang.SuppressWarnings("all") + public int hashCode() { + int result = 1; + return result; + } + @java.lang.Override + @java.lang.SuppressWarnings("all") + public java.lang.String toString() { + return "ValueExperimental2()"; + } +} \ No newline at end of file diff --git a/test/transform/resource/after-delombok/ValueExperimentalStarImport.java b/test/transform/resource/after-delombok/ValueExperimentalStarImport.java new file mode 100644 index 00000000..6911f260 --- /dev/null +++ b/test/transform/resource/after-delombok/ValueExperimentalStarImport.java @@ -0,0 +1,25 @@ +import lombok.experimental.*; +final class ValueExperimentalStarImport { + @java.lang.SuppressWarnings("all") + public ValueExperimentalStarImport() { + + } + @java.lang.Override + @java.lang.SuppressWarnings("all") + public boolean equals(final java.lang.Object o) { + if (o == this) return true; + if (!(o instanceof ValueExperimentalStarImport)) return false; + return true; + } + @java.lang.Override + @java.lang.SuppressWarnings("all") + public int hashCode() { + int result = 1; + return result; + } + @java.lang.Override + @java.lang.SuppressWarnings("all") + public java.lang.String toString() { + return "ValueExperimentalStarImport()"; + } +} \ No newline at end of file diff --git a/test/transform/resource/after-ecj/ValueExperimental.java b/test/transform/resource/after-ecj/ValueExperimental.java new file mode 100644 index 00000000..dd13574a --- /dev/null +++ b/test/transform/resource/after-ecj/ValueExperimental.java @@ -0,0 +1,39 @@ +import lombok.experimental.Value; +final @Value class ValueExperimental1 { + public @java.lang.Override @java.lang.SuppressWarnings("all") boolean equals(final java.lang.Object o) { + if ((o == this)) + return true; + if ((! (o instanceof ValueExperimental1))) + return false; + return true; + } + public @java.lang.Override @java.lang.SuppressWarnings("all") int hashCode() { + int result = 1; + return result; + } + public @java.lang.Override @java.lang.SuppressWarnings("all") java.lang.String toString() { + return "ValueExperimental1()"; + } + public @java.lang.SuppressWarnings("all") ValueExperimental1() { + super(); + } +} +final @lombok.experimental.Value class ValueExperimental2 { + public @java.lang.Override @java.lang.SuppressWarnings("all") boolean equals(final java.lang.Object o) { + if ((o == this)) + return true; + if ((! (o instanceof ValueExperimental2))) + return false; + return true; + } + public @java.lang.Override @java.lang.SuppressWarnings("all") int hashCode() { + int result = 1; + return result; + } + public @java.lang.Override @java.lang.SuppressWarnings("all") java.lang.String toString() { + return "ValueExperimental2()"; + } + public @java.lang.SuppressWarnings("all") ValueExperimental2() { + super(); + } +} \ No newline at end of file diff --git a/test/transform/resource/after-ecj/ValueExperimentalStarImport.java b/test/transform/resource/after-ecj/ValueExperimentalStarImport.java new file mode 100644 index 00000000..b69e85d9 --- /dev/null +++ b/test/transform/resource/after-ecj/ValueExperimentalStarImport.java @@ -0,0 +1,20 @@ +import lombok.experimental.*; +final @Value class ValueExperimentalStarImport { + public @java.lang.Override @java.lang.SuppressWarnings("all") boolean equals(final java.lang.Object o) { + if ((o == this)) + return true; + if ((! (o instanceof ValueExperimentalStarImport))) + return false; + return true; + } + public @java.lang.Override @java.lang.SuppressWarnings("all") int hashCode() { + int result = 1; + return result; + } + public @java.lang.Override @java.lang.SuppressWarnings("all") java.lang.String toString() { + return "ValueExperimentalStarImport()"; + } + public @java.lang.SuppressWarnings("all") ValueExperimentalStarImport() { + super(); + } +} diff --git a/test/transform/resource/after-ecj/ValuePlain.java b/test/transform/resource/after-ecj/ValuePlain.java index b798b308..d095913f 100644 --- a/test/transform/resource/after-ecj/ValuePlain.java +++ b/test/transform/resource/after-ecj/ValuePlain.java @@ -1,5 +1,5 @@ -import lombok.experimental.Value; -final @lombok.experimental.Value class Value1 { +import lombok.Value; +final @lombok.Value class Value1 { private final int x; private final String name; public @java.lang.SuppressWarnings("all") int getX() { diff --git a/test/transform/resource/before/ValueExperimental.java b/test/transform/resource/before/ValueExperimental.java new file mode 100644 index 00000000..6bae26a0 --- /dev/null +++ b/test/transform/resource/before/ValueExperimental.java @@ -0,0 +1,9 @@ +import lombok.experimental.Value; + +@Value +class ValueExperimental1 { +} + +@lombok.experimental.Value +class ValueExperimental2 { +} \ No newline at end of file diff --git a/test/transform/resource/before/ValueExperimentalStarImport.java b/test/transform/resource/before/ValueExperimentalStarImport.java new file mode 100644 index 00000000..5f18cffe --- /dev/null +++ b/test/transform/resource/before/ValueExperimentalStarImport.java @@ -0,0 +1,5 @@ +import lombok.experimental.*; + +@Value +class ValueExperimentalStarImport { +} \ No newline at end of file diff --git a/test/transform/resource/before/ValuePlain.java b/test/transform/resource/before/ValuePlain.java index 39c583cc..3fe33705 100644 --- a/test/transform/resource/before/ValuePlain.java +++ b/test/transform/resource/before/ValuePlain.java @@ -1,5 +1,5 @@ -import lombok.experimental.Value; -@lombok.experimental.Value class Value1 { +import lombok.Value; +@lombok.Value class Value1 { final int x; String name; } diff --git a/website/features/Data.html b/website/features/Data.html index 1c8510b7..ad3aa892 100644 --- a/website/features/Data.html +++ b/website/features/Data.html @@ -75,7 +75,7 @@
diff --git a/website/features/SneakyThrows.html b/website/features/SneakyThrows.html index 573bd95c..3b3987e4 100644 --- a/website/features/SneakyThrows.html +++ b/website/features/SneakyThrows.html @@ -70,7 +70,7 @@
diff --git a/website/features/Value.html b/website/features/Value.html new file mode 100644 index 00000000..92fcc825 --- /dev/null +++ b/website/features/Value.html @@ -0,0 +1,76 @@ + + + + + + + + @ExtensionMethod +
+
+
+ +

@Value

+ +
+

Since

+

+ @Value was introduced as experimental feature in lombok v0.11.4. +

+ @Value no longer implies @Wither since lombok v0.11.8. +

+ @Value promoted to the main lombok package since lombok v0.11.10. +

+
+

Overview

+

+ @Value is the immutable variant of @Data; all fields are made private and final by default, and setters are not generated. The class itself is also made final by default, because immutability is not something that can be forced onto a subclass. Like @Data, useful toString(), equals() and hashCode() methods are also generated, each field gets a getter method, and a constructor that covers every + argument (except final fields that are initialized in the field declaration) is also generated. +

+ In practice, @Value is shorthand for: final @ToString @EqualsAndHashCode @AllArgsConstructor @FieldDefaults(makeFinal = true, level = AccessLevel.PRIVATE) @Getter. +

+ It is possible to override the final-by-default and private-by-default behaviour using either an explicit access level on a field, or by using the @NonFinal or @PackagePrivate annotations.
+ It is possible to override any default behaviour for any of the 'parts' that make up @Value by explicitly using that annotation. +

+
+
+
+

With Lombok

+
@HTML_PRE@
+
+
+
+

Vanilla Java

+
@HTML_POST@
+
+
+
+
+

Small print

+

+ Look for the documentation on the 'parts' of @Value: @ToString, @EqualsAndHashCode, @AllArgsConstructor, @FieldDefaults, and @Getter. +

+ For classes with generics, it's useful to have a static method which serves as a constructor, because inference of generic parameters via static methods works in java6 and avoids having to use the diamond operator. While you can force this by applying an explicit @AllArgsConstructor(staticConstructor="of") annotation, there's also the @Value(staticConstructor="of") feature, which will make the generated all-arguments constructor private, and generates a public static method named of which is a wrapper around this private constructor. +

+ @Value was an experimental feature from v0.11.4 to v0.11.9 (as @lombok.experimental.Value). It has since been moved into the core package. The old annotation is still + around (and is an alias). It will eventually be removed in a future version, though. +

+
+ +
+
+
+ + + diff --git a/website/features/experimental/Value.html b/website/features/experimental/Value.html deleted file mode 100644 index d2acfee4..00000000 --- a/website/features/experimental/Value.html +++ /dev/null @@ -1,81 +0,0 @@ - - - - - - - - EXPERIMENTAL - @ExtensionMethod -
-
-
- -

@Value

- -
-

Since

-

- @Value was introduced as experimental feature in lombok v0.11.4. -

- @Value no longer implies @Wither since lombok v0.11.8. -

-
-

Experimental

-

- Experimental because: -

    -
  • Various choices still have to be vetted as being the correct 'least surprise' choice: Should the class be made final by default, etc.
  • -
- Current status: positive - Currently we feel this feature may move out of experimental status with no or minor changes soon. -
-
-

Overview

-

- @Value is the immutable variant of @Data; all fields are made private and final by default, and setters are not generated. The class itself is also made final by default, because immutability is not something that can be forced onto a subclass. Like @Data, useful toString(), equals() and hashCode() methods are also generated, each field gets a getter method, and a constructor that covers every - argument (except final fields that are initialized in the field declaration) is also generated. -

- In practice, @Value is shorthand for: final @ToString @EqualsAndHashCode @AllArgsConstructor @FieldDefaults(makeFinal = true, level = AccessLevel.PRIVATE) @Getter. -

- It is possible to override the final-by-default and private-by-default behaviour using either an explicit access level on a field, or by using the @NonFinal or @PackagePrivate annotations.
- It is possible to override any default behaviour for any of the 'parts' that make up @Value by explicitly using that annotation. -

-
-
-
-

With Lombok

-
@HTML_PRE@
-
-
-
-

Vanilla Java

-
@HTML_POST@
-
-
-
-
-

Small print

-

- Look for the documentation on the 'parts' of @Value: @ToString, @EqualsAndHashCode, @AllArgsConstructor, @FieldDefaults, and @Getter. -

- For classes with generics, it's useful to have a static method which serves as a constructor, because inference of generic parameters via static methods works in java6 and avoids having to use the diamond operator. While you can force this by applying an explicit @AllArgsConstructor(staticConstructor="of") annotation, there's also the @Value(staticConstructor="of") feature, which will make the generated all-arguments constructor private, and generates a public static method named of which is a wrapper around this private constructor. -

-
-
- -
-
-
- - - diff --git a/website/features/experimental/Wither.html b/website/features/experimental/Wither.html index da2156cd..9cbcd5ed 100644 --- a/website/features/experimental/Wither.html +++ b/website/features/experimental/Wither.html @@ -83,7 +83,7 @@
diff --git a/website/features/experimental/index.html b/website/features/experimental/index.html index d0a086a0..31fcd5ad 100644 --- a/website/features/experimental/index.html +++ b/website/features/experimental/index.html @@ -32,12 +32,17 @@
New default field modifiers for the 21st century.
@Wither
Immutable 'setters' - methods that create a clone but with one changed field.
-
@Value
-
Immutable classes made very easy.
onMethod= / onConstructor= / onParam
Sup dawg, we heard you like annotations, so we put annotations in your annotations so you can annotate while you're annotating.
+
+

Putting the "Ex" in "Experimental": promoted or deleted experimental features.

+
+
@Value: Promoted
+
@Value has proven its value and has been moved to the main package. +
+
diff --git a/website/features/experimental/onX.html b/website/features/experimental/onX.html index 99365deb..66b0164f 100644 --- a/website/features/experimental/onX.html +++ b/website/features/experimental/onX.html @@ -69,7 +69,7 @@
diff --git a/website/features/index.html b/website/features/index.html index 8b3765c1..f9b8cdfa 100644 --- a/website/features/index.html +++ b/website/features/index.html @@ -30,6 +30,8 @@
@Data
All together now: A shortcut for @ToString, @EqualsAndHashCode, @Getter on all fields, and @Setter on all non-final fields, and @RequiredArgsConstructor!
+
@Value
+
Immutable classes made very easy.
@SneakyThrows
To boldly throw checked exceptions where no one has thrown them before!
@Synchronized
-- cgit