From a73965b2b7b4fe2e163cdb7d104fc5dff1aa7476 Mon Sep 17 00:00:00 2001 From: Reinier Zwitserloot Date: Mon, 5 Nov 2018 23:26:59 +0100 Subject: [fixes #1918] toString now supports a configkey to tell it how to deal with super. --- doc/changelog.markdown | 2 ++ src/core/lombok/ConfigurationKeys.java | 9 ++++++- .../lombok/eclipse/handlers/HandleToString.java | 28 +++++++++++++++++----- .../lombok/javac/apt/EmptyLombokFileObject.java | 13 ++++------ src/core/lombok/javac/handlers/HandleToString.java | 28 +++++++++++++++++----- .../resource/after-delombok/ToStringAutoSuper.java | 15 ++++++++++++ .../resource/after-ecj/ToStringAutoSuper.java | 16 +++++++++++++ .../resource/before/ToStringAutoSuper.java | 8 +++++++ website/templates/features/ToString.html | 4 ++++ 9 files changed, 101 insertions(+), 22 deletions(-) create mode 100644 test/transform/resource/after-delombok/ToStringAutoSuper.java create mode 100644 test/transform/resource/after-ecj/ToStringAutoSuper.java create mode 100644 test/transform/resource/before/ToStringAutoSuper.java diff --git a/doc/changelog.markdown b/doc/changelog.markdown index 4760b5f9..78588c36 100644 --- a/doc/changelog.markdown +++ b/doc/changelog.markdown @@ -4,6 +4,8 @@ Lombok Changelog ### v1.18.5 "Edgy Guinea Pig" * BUGFIX: Since version 1.18.4, the delombok ant task didn't work and errored with a `NoClassDefFoundError`. [Issue #1932](https://github.com/rzwitserloot/lombok/issues/1932) * FEATURE: The `@FieldNameConstants` feature now allows you to write the inner type by hand and add whatever you like to it; lombok will add the constants to this class. See the updated [FieldNameConstants feature](https://projectlombok.org/features/experimental/FieldNameConstants) page. +* FEATURE: There is now a `lombok.config` key to configure `@ToString`'s call super behavior; it's just like `@EqualsAndHashCode` which has had it for a while now. [Issue #1918](https://github.com/rzwitserloot/lombok/issues/1918) + ### v1.18.4 (October 30th, 2018) * PLATFORM: Support for Eclipse Photon. [Issue #1831](https://github.com/rzwitserloot/lombok/issues/1831) * PLATFORM: Angular IDE is now recognized by the installer [Issue #1830](https://github.com/rzwitserloot/lombok/issues/1830) diff --git a/src/core/lombok/ConfigurationKeys.java b/src/core/lombok/ConfigurationKeys.java index 2cca27fa..dfcb3e33 100644 --- a/src/core/lombok/ConfigurationKeys.java +++ b/src/core/lombok/ConfigurationKeys.java @@ -214,7 +214,7 @@ public class ConfigurationKeys { * * For any class with an {@code @EqualsAndHashCode} annotation which extends a class other than {@code java.lang.Object}, should a call to superclass's implementation of {@code equals} and {@code hashCode} be included in the generated methods? (Default = warn) */ - public static final ConfigurationKey EQUALS_AND_HASH_CODE_CALL_SUPER = new ConfigurationKey("lombok.equalsAndHashCode.callSuper", "When generating equals and hashCode for classes that don't extend Object, either automatically take into account superclass implementation (call), or don't (skip), or warn and don't (warn). (default = warn).") {}; + public static final ConfigurationKey EQUALS_AND_HASH_CODE_CALL_SUPER = new ConfigurationKey("lombok.equalsAndHashCode.callSuper", "When generating equals and hashCode for classes that extend something (other than Object), either automatically take into account superclass implementation (call), or don't (skip), or warn and don't (warn). (default = warn).") {}; /** * lombok configuration: {@code lombok.equalsAndHashCode.flagUsage} = {@code WARNING} | {@code ERROR}. @@ -232,6 +232,13 @@ public class ConfigurationKeys { */ public static final ConfigurationKey TO_STRING_DO_NOT_USE_GETTERS = new ConfigurationKey("lombok.toString.doNotUseGetters", "Don't call the getters but use the fields directly in the generated toString method (default = false).") {}; + /** + * lombok configuration: {@code lombok.toString.callSuper} = {@code call} | {@code ignore} | {@code warn}. + * + * For any class with an {@code @ToString} annotation which extends a class other than {@code java.lang.Object}, should a call to superclass's implementation of {@code toString} be included in the generated method? (Default = skip) + */ + public static final ConfigurationKey TO_STRING_CALL_SUPER = new ConfigurationKey("lombok.toString.callSuper", "When generating toString for classes that extend something (other than Object), either automatically take into account superclass implementation (call), or don't (skip), or warn and don't (warn). (default = warn).") {}; + /** * lombok configuration: {@code lombok.toString.flagUsage} = {@code WARNING} | {@code ERROR}. * diff --git a/src/core/lombok/eclipse/handlers/HandleToString.java b/src/core/lombok/eclipse/handlers/HandleToString.java index 02a19f8d..303e5bea 100644 --- a/src/core/lombok/eclipse/handlers/HandleToString.java +++ b/src/core/lombok/eclipse/handlers/HandleToString.java @@ -36,6 +36,7 @@ import lombok.ConfigurationKeys; import lombok.ToString; import lombok.core.AST.Kind; import lombok.core.AnnotationValues; +import lombok.core.configuration.CallSuperType; import lombok.core.handlers.InclusionExclusionUtils; import lombok.core.handlers.InclusionExclusionUtils.Included; import lombok.eclipse.Eclipse; @@ -119,12 +120,6 @@ public class HandleToString extends EclipseAnnotationHandler { boolean notAClass = (modifiers & (ClassFileConstants.AccInterface | ClassFileConstants.AccAnnotation)) != 0; - if (callSuper == null) { - try { - callSuper = ((Boolean)ToString.class.getMethod("callSuper").getDefaultValue()).booleanValue(); - } catch (Exception ignore) {} - } - if (typeDecl == null || notAClass) { errorNode.addError("@ToString is only supported on a class or enum."); return; @@ -132,6 +127,27 @@ public class HandleToString extends EclipseAnnotationHandler { switch (methodExists("toString", typeNode, 0)) { case NOT_EXISTS: + if (callSuper == null) { + if (isDirectDescendantOfObject(typeNode)) { + callSuper = false; + } else { + CallSuperType cst = typeNode.getAst().readConfiguration(ConfigurationKeys.TO_STRING_CALL_SUPER); + if (cst == null) cst = CallSuperType.SKIP; + switch (cst) { + default: + case SKIP: + callSuper = false; + break; + case WARN: + errorNode.addWarning("Generating toString implementation but without a call to superclass, even though this class does not extend java.lang.Object. If this intentional, add '@ToString(callSuper=false)' to your type."); + callSuper = false; + break; + case CALL: + callSuper = true; + break; + } + } + } MethodDeclaration toString = createToString(typeNode, members, includeFieldNames, callSuper, errorNode.get(), fieldAccess); injectMethod(typeNode, toString); break; diff --git a/src/core/lombok/javac/apt/EmptyLombokFileObject.java b/src/core/lombok/javac/apt/EmptyLombokFileObject.java index 84bb00e4..d1d00582 100644 --- a/src/core/lombok/javac/apt/EmptyLombokFileObject.java +++ b/src/core/lombok/javac/apt/EmptyLombokFileObject.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010-2011 The Project Lombok Authors. + * Copyright (C) 2010-2018 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,8 +52,7 @@ class EmptyLombokFileObject implements LombokFileObject { @Override public boolean isNameCompatible(String simpleName, Kind kind) { String baseName = simpleName + kind.extension; return kind.equals(getKind()) - && (baseName.equals(toUri().getPath()) - || toUri().getPath().endsWith("/" + baseName)); + && (baseName.equals(toUri().getPath()) || toUri().getPath().endsWith("/" + baseName)); } @Override public URI toUri() { @@ -112,12 +111,8 @@ class EmptyLombokFileObject implements LombokFileObject { } @Override public boolean equals(Object obj) { - if (!(obj instanceof EmptyLombokFileObject)) { - return false; - } - if (obj == this) { - return true; - } + if (!(obj instanceof EmptyLombokFileObject)) return false; + if (obj == this) return true; EmptyLombokFileObject other = (EmptyLombokFileObject) obj; return name.equals(other.name) && kind.equals(other.kind); } diff --git a/src/core/lombok/javac/handlers/HandleToString.java b/src/core/lombok/javac/handlers/HandleToString.java index 28d18357..eb6e56f3 100644 --- a/src/core/lombok/javac/handlers/HandleToString.java +++ b/src/core/lombok/javac/handlers/HandleToString.java @@ -30,6 +30,7 @@ import java.util.Collection; import lombok.ConfigurationKeys; import lombok.ToString; import lombok.core.AnnotationValues; +import lombok.core.configuration.CallSuperType; import lombok.core.AST.Kind; import lombok.core.handlers.InclusionExclusionUtils; import lombok.core.handlers.InclusionExclusionUtils.Included; @@ -111,12 +112,6 @@ public class HandleToString extends JavacAnnotationHandler { notAClass = (flags & (Flags.INTERFACE | Flags.ANNOTATION)) != 0; } - if (callSuper == null) { - try { - callSuper = ((Boolean) ToString.class.getMethod("callSuper").getDefaultValue()).booleanValue(); - } catch (Exception ignore) {} - } - if (notAClass) { source.addError("@ToString is only supported on a class or enum."); return; @@ -124,6 +119,27 @@ public class HandleToString extends JavacAnnotationHandler { switch (methodExists("toString", typeNode, 0)) { case NOT_EXISTS: + if (callSuper == null) { + if (isDirectDescendantOfObject(typeNode)) { + callSuper = false; + } else { + CallSuperType cst = typeNode.getAst().readConfiguration(ConfigurationKeys.TO_STRING_CALL_SUPER); + if (cst == null) cst = CallSuperType.SKIP; + switch (cst) { + default: + case SKIP: + callSuper = false; + break; + case WARN: + source.addWarning("Generating toString implementation but without a call to superclass, even though this class does not extend java.lang.Object. If this is intentional, add '@ToString(callSuper=false)' to your type."); + callSuper = false; + break; + case CALL: + callSuper = true; + break; + } + } + } JCMethodDecl method = createToString(typeNode, members, includeFieldNames, callSuper, fieldAccess, source.get()); injectMethod(typeNode, method); break; diff --git a/test/transform/resource/after-delombok/ToStringAutoSuper.java b/test/transform/resource/after-delombok/ToStringAutoSuper.java new file mode 100644 index 00000000..1fe59581 --- /dev/null +++ b/test/transform/resource/after-delombok/ToStringAutoSuper.java @@ -0,0 +1,15 @@ +class ToStringAutoSuperWithNoParent { + @java.lang.Override + @java.lang.SuppressWarnings("all") + public java.lang.String toString() { + return "ToStringAutoSuperWithNoParent()"; + } +} + +class ToStringAutoSuperWithParent extends ToStringAutoSuperWithNoParent { + @java.lang.Override + @java.lang.SuppressWarnings("all") + public java.lang.String toString() { + return "ToStringAutoSuperWithParent(super=" + super.toString() + ")"; + } +} diff --git a/test/transform/resource/after-ecj/ToStringAutoSuper.java b/test/transform/resource/after-ecj/ToStringAutoSuper.java new file mode 100644 index 00000000..fb468ddc --- /dev/null +++ b/test/transform/resource/after-ecj/ToStringAutoSuper.java @@ -0,0 +1,16 @@ +@lombok.ToString class ToStringAutoSuperWithNoParent { + ToStringAutoSuperWithNoParent() { + super(); + } + public @java.lang.Override @java.lang.SuppressWarnings("all") java.lang.String toString() { + return "ToStringAutoSuperWithNoParent()"; + } +} +@lombok.ToString class ToStringAutoSuperWithParent extends ToStringAutoSuperWithNoParent { + ToStringAutoSuperWithParent() { + super(); + } + public @java.lang.Override @java.lang.SuppressWarnings("all") java.lang.String toString() { + return (("ToStringAutoSuperWithParent(super=" + super.toString()) + ")"); + } +} diff --git a/test/transform/resource/before/ToStringAutoSuper.java b/test/transform/resource/before/ToStringAutoSuper.java new file mode 100644 index 00000000..e98664ba --- /dev/null +++ b/test/transform/resource/before/ToStringAutoSuper.java @@ -0,0 +1,8 @@ +//CONF: lombok.toString.callSuper = CALL +@lombok.ToString +class ToStringAutoSuperWithNoParent { +} + +@lombok.ToString +class ToStringAutoSuperWithParent extends ToStringAutoSuperWithNoParent { +} diff --git a/website/templates/features/ToString.html b/website/templates/features/ToString.html index d31cf35d..d2644629 100644 --- a/website/templates/features/ToString.html +++ b/website/templates/features/ToString.html @@ -28,6 +28,10 @@ lombok.toString.doNotUseGetters = [true | false] (default: false)
If set to true, lombok will access fields directly instead of using getters (if available) when generating toString methods. The annotation parameter 'doNotUseGetters', if explicitly specified, takes precedence over this setting. +
+ lombok.toString.callSuper = [call | skip | warn] (default: skip) +
+ If set to call, lombok will generate calls to the superclass implementation of toString if your class extends something. If set to skip no such call is generated. If set to warn no such call is generated either, but lombok does generate a warning to tell you about it.
lombok.toString.flagUsage = [warning | error] (default: not set)
-- cgit