From 58a7914027e3373faa942aa4ce7df2d3ebfb9a20 Mon Sep 17 00:00:00 2001 From: Reinier Zwitserloot Date: Wed, 4 Feb 2015 00:08:48 +0100 Subject: @UtilityClass handlers now more intelligent about inner types of implicitly static contexts (enums, interfaces, and annotation declarations). Also added tests to test for these. --- .../eclipse/handlers/HandleUtilityClass.java | 16 +++++++++++--- .../lombok/javac/handlers/HandleUtilityClass.java | 22 +++++++++++++------ src/utils/lombok/javac/TreeMirrorMaker.java | 14 ------------ .../resource/after-delombok/UtilityClass.java | 22 +++++++++++++++++++ .../after-delombok/UtilityClassErrors.java | 7 ++++++ .../transform/resource/after-ecj/UtilityClass.java | 25 ++++++++++++++++++++++ .../resource/after-ecj/UtilityClassErrors.java | 16 ++++++++++++++ test/transform/resource/before/UtilityClass.java | 17 +++++++++++++++ .../resource/before/UtilityClassErrors.java | 8 +++++++ .../UtilityClassErrors.java.messages | 1 + .../messages-ecj/UtilityClassErrors.java.messages | 3 ++- 11 files changed, 126 insertions(+), 25 deletions(-) diff --git a/src/core/lombok/eclipse/handlers/HandleUtilityClass.java b/src/core/lombok/eclipse/handlers/HandleUtilityClass.java index 36a7dc9c..176ff2d8 100644 --- a/src/core/lombok/eclipse/handlers/HandleUtilityClass.java +++ b/src/core/lombok/eclipse/handlers/HandleUtilityClass.java @@ -83,8 +83,10 @@ public class HandleUtilityClass extends EclipseAnnotationHandler { typeWalk = typeWalk.up(); switch (typeWalk.getKind()) { case TYPE: - if ((((TypeDeclaration) typeWalk.get()).modifiers & ClassFileConstants.AccStatic) != 0) continue; + if ((((TypeDeclaration) typeWalk.get()).modifiers & (ClassFileConstants.AccStatic | ClassFileConstants.AccInterface | ClassFileConstants.AccAnnotation | ClassFileConstants.AccEnum)) != 0) continue; if (typeWalk.up().getKind() == Kind.COMPILATION_UNIT) return true; + errorNode.addError("@UtilityClass automatically makes the class static, however, this class cannot be made static."); + return false; case COMPILATION_UNIT: return true; default: @@ -101,7 +103,15 @@ public class HandleUtilityClass extends EclipseAnnotationHandler { classDecl.modifiers |= ClassFileConstants.AccFinal; - if (typeNode.up().getKind() != Kind.COMPILATION_UNIT) classDecl.modifiers |= ClassFileConstants.AccStatic; + boolean markStatic = true; + + if (typeNode.up().getKind() == Kind.COMPILATION_UNIT) markStatic = false; + if (markStatic && typeNode.up().getKind() == Kind.TYPE) { + TypeDeclaration typeDecl = (TypeDeclaration) typeNode.up().get(); + if ((typeDecl.modifiers & ClassFileConstants.AccInterface) != 0) markStatic = false; + } + + if (markStatic) classDecl.modifiers |= ClassFileConstants.AccStatic; for (EclipseNode element : typeNode.down()) { if (element.getKind() == Kind.FIELD) { @@ -155,7 +165,7 @@ public class HandleUtilityClass extends EclipseAnnotationHandler { AllocationExpression exception = new AllocationExpression(); setGeneratedBy(exception, source); - long[] ps = new long[3]; + long[] ps = new long[JAVA_LANG_UNSUPPORTED_OPERATION_EXCEPTION.length]; Arrays.fill(ps, p); exception.type = new QualifiedTypeReference(JAVA_LANG_UNSUPPORTED_OPERATION_EXCEPTION, ps); setGeneratedBy(exception.type, source); diff --git a/src/core/lombok/javac/handlers/HandleUtilityClass.java b/src/core/lombok/javac/handlers/HandleUtilityClass.java index 9a37653e..a4f8cb45 100644 --- a/src/core/lombok/javac/handlers/HandleUtilityClass.java +++ b/src/core/lombok/javac/handlers/HandleUtilityClass.java @@ -44,7 +44,6 @@ import com.sun.tools.javac.tree.JCTree.JCStatement; import com.sun.tools.javac.tree.JCTree.JCTypeParameter; import com.sun.tools.javac.tree.JCTree.JCVariableDecl; import com.sun.tools.javac.util.List; -import com.sun.tools.javac.util.ListBuffer; import com.sun.tools.javac.util.Name; /** @@ -79,8 +78,11 @@ public class HandleUtilityClass extends JavacAnnotationHandler { typeWalk = typeWalk.up(); switch (typeWalk.getKind()) { case TYPE: - if ((((JCClassDecl) typeWalk.get()).mods.flags & Flags.STATIC) != 0) continue; + JCClassDecl typeDef = (JCClassDecl) typeWalk.get(); + if ((typeDef.mods.flags & (Flags.STATIC | Flags.ANNOTATION | Flags.ENUM | Flags.INTERFACE)) != 0) continue; if (typeWalk.up().getKind() == Kind.COMPILATION_UNIT) return true; + errorNode.addError("@UtilityClass automatically makes the class static, however, this class cannot be made static."); + return false; case COMPILATION_UNIT: return true; default: @@ -97,7 +99,15 @@ public class HandleUtilityClass extends JavacAnnotationHandler { classDecl.mods.flags |= Flags.FINAL; - if (typeNode.up().getKind() != Kind.COMPILATION_UNIT) classDecl.mods.flags |= Flags.STATIC; + boolean markStatic = true; + + if (typeNode.up().getKind() == Kind.COMPILATION_UNIT) markStatic = false; + if (markStatic && typeNode.up().getKind() == Kind.TYPE) { + JCClassDecl typeDecl = (JCClassDecl) typeNode.up().get(); + if ((typeDecl.mods.flags & Flags.INTERFACE) != 0) markStatic = false; + } + + if (markStatic) classDecl.mods.flags |= Flags.STATIC; for (JavacNode element : typeNode.down()) { if (element.getKind() == Kind.FIELD) { @@ -135,13 +145,11 @@ public class HandleUtilityClass extends JavacAnnotationHandler { } private List createThrowStatement(JavacNode typeNode, JavacTreeMaker maker) { - ListBuffer statements = new ListBuffer(); - JCExpression exceptionType = genTypeRef(typeNode, "java.lang.UnsupportedOperationException"); + JCExpression exceptionType = genJavaLangTypeRef(typeNode, "UnsupportedOperationException"); List jceBlank = List.nil(); JCExpression message = maker.Literal("This is a utility class and cannot be instantiated"); JCExpression exceptionInstance = maker.NewClass(null, jceBlank, exceptionType, List.of(message), null); JCStatement throwStatement = maker.Throw(exceptionInstance); - statements.add(throwStatement); - return statements.toList(); + return List.of(throwStatement); } } diff --git a/src/utils/lombok/javac/TreeMirrorMaker.java b/src/utils/lombok/javac/TreeMirrorMaker.java index 093839d7..918a3242 100644 --- a/src/utils/lombok/javac/TreeMirrorMaker.java +++ b/src/utils/lombok/javac/TreeMirrorMaker.java @@ -29,13 +29,9 @@ import java.util.Map; import static lombok.javac.Javac.*; import lombok.javac.JavacTreeMaker.TypeTag; -import com.sun.source.tree.ClassTree; import com.sun.source.tree.LabeledStatementTree; -import com.sun.source.tree.NewClassTree; import com.sun.source.tree.VariableTree; import com.sun.tools.javac.tree.JCTree; -import com.sun.tools.javac.tree.JCTree.JCClassDecl; -import com.sun.tools.javac.tree.JCTree.JCNewClass; import com.sun.tools.javac.tree.JCTree.JCVariableDecl; import com.sun.tools.javac.tree.TreeCopier; import com.sun.tools.javac.util.Context; @@ -123,14 +119,4 @@ public class TreeMirrorMaker extends TreeCopier { @Override public JCTree visitLabeledStatement(LabeledStatementTree node, Void p) { return node.getStatement().accept(this, p); } - - @Override public JCTree visitNewClass(NewClassTree node, Void p) { - JCNewClass copy = (JCNewClass) super.visitNewClass(node, p); - return copy; - } - - @Override public JCTree visitClass(ClassTree node, Void p) { - JCClassDecl copy = (JCClassDecl) super.visitClass(node, p); - return copy; - } } diff --git a/test/transform/resource/after-delombok/UtilityClass.java b/test/transform/resource/after-delombok/UtilityClass.java index f9fe02a0..eb7eef09 100644 --- a/test/transform/resource/after-delombok/UtilityClass.java +++ b/test/transform/resource/after-delombok/UtilityClass.java @@ -23,4 +23,26 @@ class UtilityInner { } } } + enum UtilityInsideEnum { + FOO, + BAR; + static final class InsideEnum { + static int member; + @java.lang.SuppressWarnings("all") + @javax.annotation.Generated("lombok") + private InsideEnum() { + throw new java.lang.UnsupportedOperationException("This is a utility class and cannot be instantiated"); + } + } + } + interface UtilityInsideInterface { + final class InsideInterface { + static int member; + @java.lang.SuppressWarnings("all") + @javax.annotation.Generated("lombok") + private InsideInterface() { + throw new java.lang.UnsupportedOperationException("This is a utility class and cannot be instantiated"); + } + } + } } \ No newline at end of file diff --git a/test/transform/resource/after-delombok/UtilityClassErrors.java b/test/transform/resource/after-delombok/UtilityClassErrors.java index b19b4e72..9626461a 100644 --- a/test/transform/resource/after-delombok/UtilityClassErrors.java +++ b/test/transform/resource/after-delombok/UtilityClassErrors.java @@ -9,4 +9,11 @@ final class UtilityClassErrors1 { } enum UtilityClassErrors2 { ; +} +class UtilityClassErrors3 { + class NonStaticInner { + class ThisShouldFail { + private String member; + } + } } \ No newline at end of file diff --git a/test/transform/resource/after-ecj/UtilityClass.java b/test/transform/resource/after-ecj/UtilityClass.java index c3e06fbc..e8db6a21 100644 --- a/test/transform/resource/after-ecj/UtilityClass.java +++ b/test/transform/resource/after-ecj/UtilityClass.java @@ -27,6 +27,31 @@ class UtilityInner { super(); } } + 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"); + } + } + FOO(), + BAR(), + () { + } + UtilityInsideEnum() { + super(); + } + } + 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"); + } + } + } UtilityInner() { super(); } diff --git a/test/transform/resource/after-ecj/UtilityClassErrors.java b/test/transform/resource/after-ecj/UtilityClassErrors.java index 03206592..26b331a1 100644 --- a/test/transform/resource/after-ecj/UtilityClassErrors.java +++ b/test/transform/resource/after-ecj/UtilityClassErrors.java @@ -18,3 +18,19 @@ final @lombok.experimental.UtilityClass class UtilityClassErrors1 { super(); } } +class UtilityClassErrors3 { + class NonStaticInner { + @lombok.experimental.UtilityClass class ThisShouldFail { + private String member; + ThisShouldFail() { + super(); + } + } + NonStaticInner() { + super(); + } + } + UtilityClassErrors3() { + super(); + } +} diff --git a/test/transform/resource/before/UtilityClass.java b/test/transform/resource/before/UtilityClass.java index ccfa43e1..0f9875f0 100644 --- a/test/transform/resource/before/UtilityClass.java +++ b/test/transform/resource/before/UtilityClass.java @@ -10,6 +10,7 @@ class UtilityClass { private String innerInnerMember; } } + class UtilityInner { static class InnerInner { @lombok.experimental.UtilityClass @@ -17,4 +18,20 @@ class UtilityInner { int member; } } + + enum UtilityInsideEnum { + FOO, BAR; + + @lombok.experimental.UtilityClass + class InsideEnum { + int member; + } + } + + interface UtilityInsideInterface { + @lombok.experimental.UtilityClass + class InsideInterface { + int member; + } + } } diff --git a/test/transform/resource/before/UtilityClassErrors.java b/test/transform/resource/before/UtilityClassErrors.java index 5f72274b..d750e2bd 100644 --- a/test/transform/resource/before/UtilityClassErrors.java +++ b/test/transform/resource/before/UtilityClassErrors.java @@ -11,4 +11,12 @@ class UtilityClassErrors1 { } @lombok.experimental.UtilityClass enum UtilityClassErrors2 { +} +class UtilityClassErrors3 { + class NonStaticInner { + @lombok.experimental.UtilityClass + class ThisShouldFail { + private String member; + } + } } \ No newline at end of file diff --git a/test/transform/resource/messages-delombok/UtilityClassErrors.java.messages b/test/transform/resource/messages-delombok/UtilityClassErrors.java.messages index 230ba04f..4afa12ec 100644 --- a/test/transform/resource/messages-delombok/UtilityClassErrors.java.messages +++ b/test/transform/resource/messages-delombok/UtilityClassErrors.java.messages @@ -1,3 +1,4 @@ 4 @UtilityClasses cannot have declared constructors. 7 @UtilityClass cannot be placed on a method local or anonymous inner class, or any class nested in such a class. 12 @UtilityClass is only supported on a class (can't be an interface, enum, or annotation). +17 @UtilityClass automatically makes the class static, however, this class cannot be made static. \ No newline at end of file diff --git a/test/transform/resource/messages-ecj/UtilityClassErrors.java.messages b/test/transform/resource/messages-ecj/UtilityClassErrors.java.messages index c80a18dc..15c9b10f 100644 --- a/test/transform/resource/messages-ecj/UtilityClassErrors.java.messages +++ b/test/transform/resource/messages-ecj/UtilityClassErrors.java.messages @@ -1,3 +1,4 @@ 4 @UtilityClasses cannot have declared constructors. 7 @UtilityClass cannot be placed on a method local or anonymous inner class, or any class nested in such a class. -12 @UtilityClass is only supported on a class (can't be an interface, enum, or annotation) \ No newline at end of file +12 @UtilityClass is only supported on a class (can't be an interface, enum, or annotation) +17 @UtilityClass automatically makes the class static, however, this class cannot be made static. \ No newline at end of file -- cgit