From de816ebbcde3daea556e250c85723c867221016f Mon Sep 17 00:00:00 2001 From: Reinier Zwitserloot Date: Tue, 14 Apr 2015 21:54:04 +0200 Subject: [i804] @UtilityClass fails to properly initialize fields (which @UtilityClass makes static) with initializers, in eclipse. also updates the changelog more generally, it was lacking some recent work. --- doc/changelog.markdown | 5 ++++- src/core/lombok/eclipse/handlers/HandleUtilityClass.java | 11 ++++++++++- test/transform/resource/after-delombok/UtilityClass.java | 2 +- test/transform/resource/after-ecj/UtilityClass.java | 10 +++++++++- test/transform/resource/after-ecj/UtilityClassErrors.java | 2 ++ test/transform/resource/before/UtilityClass.java | 2 +- 6 files changed, 27 insertions(+), 5 deletions(-) diff --git a/doc/changelog.markdown b/doc/changelog.markdown index 9ceb3010..20c9ae61 100644 --- a/doc/changelog.markdown +++ b/doc/changelog.markdown @@ -2,13 +2,16 @@ Lombok Changelog ---------------- ### v1.16.3 "Edgy Guinea Pig" +* BUGFIX: Lombok now works with Eclipse Mars. +* BUGFIX: @UtilityClass could result in uninitialized static variables if compiled with ecj/eclipse. [Issue #804](https://code.google.com/p/projectlombok/issues/detail?id=804) +* BUGFIX: This version of lombok has a refactored launcher (the one introduced in v1.16.0), which fixes various bugs related to errors in eclipse concerning loading classes, failure to find lombok classes, and errors on ClassLoaders. Probably impacts issues [#732](https://code.google.com/p/projectlombok/issues/detail?id=732) and [#791](https://code.google.com/p/projectlombok/issues/detail?id=791). ### v1.16.2 (February 10th, 2015) * FEATURE: The config key `lombok.extern.findbugs.addSuppressFBWarnings` can now be used to add findbugs suppress warnings annotations to all code lombok generates. This addresses feature request [Issue #702](https://code.google.com/p/projectlombok/issues/detail?id=702). * FEATURE: New lombok annotation: `@UtilityClass`, for making utility classes (not instantiable, contains only static 'function' methods). See the [feature documentation](http://projectlombok.org/features/experimental/UtilityClass.html) for more information. * BUGFIX: The ant `delombok` task was broken starting with v1.16.0. Note that the task def class has been changed; taskdef `lombok.delombok.ant.Tasks$Delombok` instead of the old `lombok.delombok.ant.DelombokTask`. [Issue #775](https://code.google.com/p/projectlombok/issues/detail?id=775). * BUGFIX: `val` in javac would occasionally fail if used inside inner classes. This is (probably) fixed. [Issue #694](https://code.google.com/p/projectlombok/issues/detail?id=694) and [Issue #581](https://code.google.com/p/projectlombok/issues/detail?id=581). -* BUGFIX: Starting with v1.16.0, lombok would fail to execute as an executable jar if it was in a path was spaced in it. [Issue #777](https://code.google.com/p/projectlombok/issues/detail?id=777). +* BUGFIX: Starting with v1.16.0, lombok would fail to execute as an executable jar if it was in a path with spaces in it. [Issue #777](https://code.google.com/p/projectlombok/issues/detail?id=777). * BUGFIX: v1.16.0 did not work in old eclipse versions (such as eclipse indigo). [Issue #783](https://code.google.com/p/projectlombok/issues/detail?id=783). ### v1.16.0 "Candid Duck" (January 26th, 2015) diff --git a/src/core/lombok/eclipse/handlers/HandleUtilityClass.java b/src/core/lombok/eclipse/handlers/HandleUtilityClass.java index 176ff2d8..c3c85ad4 100644 --- a/src/core/lombok/eclipse/handlers/HandleUtilityClass.java +++ b/src/core/lombok/eclipse/handlers/HandleUtilityClass.java @@ -31,6 +31,7 @@ import org.eclipse.jdt.internal.compiler.ast.ASTNode; import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration; import org.eclipse.jdt.internal.compiler.ast.AllocationExpression; import org.eclipse.jdt.internal.compiler.ast.Annotation; +import org.eclipse.jdt.internal.compiler.ast.Clinit; import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration; import org.eclipse.jdt.internal.compiler.ast.ConstructorDeclaration; import org.eclipse.jdt.internal.compiler.ast.ExplicitConstructorCall; @@ -104,6 +105,8 @@ public class HandleUtilityClass extends EclipseAnnotationHandler { classDecl.modifiers |= ClassFileConstants.AccFinal; boolean markStatic = true; + boolean requiresClInit = false; + boolean alreadyHasClinit = false; if (typeNode.up().getKind() == Kind.COMPILATION_UNIT) markStatic = false; if (markStatic && typeNode.up().getKind() == Kind.TYPE) { @@ -116,7 +119,10 @@ public class HandleUtilityClass extends EclipseAnnotationHandler { for (EclipseNode element : typeNode.down()) { if (element.getKind() == Kind.FIELD) { FieldDeclaration fieldDecl = (FieldDeclaration) element.get(); - fieldDecl.modifiers |= ClassFileConstants.AccStatic; + if ((fieldDecl.modifiers & ClassFileConstants.AccStatic) == 0) { + requiresClInit = true; + fieldDecl.modifiers |= ClassFileConstants.AccStatic; + } } else if (element.getKind() == Kind.METHOD) { AbstractMethodDeclaration amd = (AbstractMethodDeclaration) element.get(); if (amd instanceof ConstructorDeclaration) { @@ -128,6 +134,8 @@ public class HandleUtilityClass extends EclipseAnnotationHandler { } } else if (amd instanceof MethodDeclaration) { amd.modifiers |= ClassFileConstants.AccStatic; + } else if (amd instanceof Clinit) { + alreadyHasClinit = true; } } else if (element.getKind() == Kind.TYPE) { ((TypeDeclaration) element.get()).modifiers |= ClassFileConstants.AccStatic; @@ -135,6 +143,7 @@ public class HandleUtilityClass extends EclipseAnnotationHandler { } if (makeConstructor) createPrivateDefaultConstructor(typeNode, annotationNode); + if (requiresClInit && !alreadyHasClinit) classDecl.addClinit(); } private static final char[][] JAVA_LANG_UNSUPPORTED_OPERATION_EXCEPTION = new char[][] { diff --git a/test/transform/resource/after-delombok/UtilityClass.java b/test/transform/resource/after-delombok/UtilityClass.java index eb7eef09..7731b49c 100644 --- a/test/transform/resource/after-delombok/UtilityClass.java +++ b/test/transform/resource/after-delombok/UtilityClass.java @@ -1,5 +1,5 @@ final class UtilityClass { - private static String someField; + private static long someField = System.currentTimeMillis(); static void someMethod() { System.out.println(); } diff --git a/test/transform/resource/after-ecj/UtilityClass.java b/test/transform/resource/after-ecj/UtilityClass.java index e8db6a21..81d5d9e6 100644 --- a/test/transform/resource/after-ecj/UtilityClass.java +++ b/test/transform/resource/after-ecj/UtilityClass.java @@ -5,7 +5,9 @@ final @lombok.experimental.UtilityClass class UtilityClass { super(); } } - private static String someField; + private static long someField = System.currentTimeMillis(); + () { + } static void someMethod() { System.out.println(); } @@ -18,6 +20,8 @@ class UtilityInner { static class InnerInner { static final @lombok.experimental.UtilityClass class InnerInnerInner { static int member; + () { + } private @java.lang.SuppressWarnings("all") @javax.annotation.Generated("lombok") InnerInnerInner() { super(); throw new java.lang.UnsupportedOperationException("This is a utility class and cannot be instantiated"); @@ -30,6 +34,8 @@ class UtilityInner { enum UtilityInsideEnum { static final @lombok.experimental.UtilityClass class InsideEnum { static int member; + () { + } private @java.lang.SuppressWarnings("all") @javax.annotation.Generated("lombok") InsideEnum() { super(); throw new java.lang.UnsupportedOperationException("This is a utility class and cannot be instantiated"); @@ -46,6 +52,8 @@ class UtilityInner { interface UtilityInsideInterface { final @lombok.experimental.UtilityClass class InsideInterface { static int member; + () { + } private @java.lang.SuppressWarnings("all") @javax.annotation.Generated("lombok") InsideInterface() { super(); throw new java.lang.UnsupportedOperationException("This is a utility class and cannot be instantiated"); diff --git a/test/transform/resource/after-ecj/UtilityClassErrors.java b/test/transform/resource/after-ecj/UtilityClassErrors.java index 26b331a1..b5a51313 100644 --- a/test/transform/resource/after-ecj/UtilityClassErrors.java +++ b/test/transform/resource/after-ecj/UtilityClassErrors.java @@ -1,5 +1,7 @@ final @lombok.experimental.UtilityClass class UtilityClassErrors1 { private static String someField; + () { + } protected UtilityClassErrors1() { super(); } diff --git a/test/transform/resource/before/UtilityClass.java b/test/transform/resource/before/UtilityClass.java index 0f9875f0..016a166e 100644 --- a/test/transform/resource/before/UtilityClass.java +++ b/test/transform/resource/before/UtilityClass.java @@ -1,6 +1,6 @@ @lombok.experimental.UtilityClass class UtilityClass { - private String someField; + private long someField = System.currentTimeMillis(); void someMethod() { System.out.println(); -- cgit