From commits-return-5369-archive-asf-public=cust-asf.ponee.io@groovy.apache.org Sun Feb 4 10:42:46 2018 Return-Path: X-Original-To: archive-asf-public@eu.ponee.io Delivered-To: archive-asf-public@eu.ponee.io Received: from cust-asf.ponee.io (cust-asf.ponee.io [163.172.22.183]) by mx-eu-01.ponee.io (Postfix) with ESMTP id A1AF018064A for ; Sun, 4 Feb 2018 10:42:46 +0100 (CET) Received: by cust-asf.ponee.io (Postfix) id 90993160C40; Sun, 4 Feb 2018 09:42:46 +0000 (UTC) Delivered-To: archive-asf-public@cust-asf.ponee.io Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by cust-asf.ponee.io (Postfix) with SMTP id B2807160C37 for ; Sun, 4 Feb 2018 10:42:45 +0100 (CET) Received: (qmail 66615 invoked by uid 500); 4 Feb 2018 09:42:44 -0000 Mailing-List: contact commits-help@groovy.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@groovy.apache.org Delivered-To: mailing list commits@groovy.apache.org Received: (qmail 66606 invoked by uid 99); 4 Feb 2018 09:42:44 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Sun, 04 Feb 2018 09:42:44 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id CD525E9638; Sun, 4 Feb 2018 09:42:44 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: paulk@apache.org To: commits@groovy.apache.org Message-Id: <254afb2b077843d19a4acf47c4d5ce98@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: groovy git commit: improve doco for immutable-related annotations Date: Sun, 4 Feb 2018 09:42:44 +0000 (UTC) Repository: groovy Updated Branches: refs/heads/GROOVY_2_5_X e358915fd -> 82f1d4c4a improve doco for immutable-related annotations Project: http://git-wip-us.apache.org/repos/asf/groovy/repo Commit: http://git-wip-us.apache.org/repos/asf/groovy/commit/82f1d4c4 Tree: http://git-wip-us.apache.org/repos/asf/groovy/tree/82f1d4c4 Diff: http://git-wip-us.apache.org/repos/asf/groovy/diff/82f1d4c4 Branch: refs/heads/GROOVY_2_5_X Commit: 82f1d4c4ac4a043585fbb1a5f908787a36064f25 Parents: e358915 Author: paulk Authored: Sun Feb 4 18:41:57 2018 +1000 Committer: paulk Committed: Sun Feb 4 19:42:33 2018 +1000 ---------------------------------------------------------------------- .../transform/ImmutableASTTransformation.java | 4 +- src/spec/doc/core-metaprogramming.adoc | 64 +++++++++++++++++--- 2 files changed, 57 insertions(+), 11 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/groovy/blob/82f1d4c4/src/main/java/org/codehaus/groovy/transform/ImmutableASTTransformation.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/codehaus/groovy/transform/ImmutableASTTransformation.java b/src/main/java/org/codehaus/groovy/transform/ImmutableASTTransformation.java index 9e25e18..79c7c46 100644 --- a/src/main/java/org/codehaus/groovy/transform/ImmutableASTTransformation.java +++ b/src/main/java/org/codehaus/groovy/transform/ImmutableASTTransformation.java @@ -233,6 +233,7 @@ public class ImmutableASTTransformation extends AbstractASTTransformation { if (unsupportedTupleAttribute(tupleCons, "includeProperties")) return; if (unsupportedTupleAttribute(tupleCons, "includeSuperFields")) return; if (unsupportedTupleAttribute(tupleCons, "callSuper")) return; + if (unsupportedTupleAttribute(tupleCons, "useSetters")) return; if (unsupportedTupleAttribute(tupleCons, "force")) return; } if (!validateConstructors(cNode)) return; @@ -341,9 +342,9 @@ public class ImmutableASTTransformation extends AbstractASTTransformation { return list.size() == 1 && list.get(0).getField().getType().equals(HASHMAP_TYPE); } + @Deprecated static List getProperties(ClassNode cNode, boolean includeSuperProperties, boolean allProperties) { List list = getInstanceProperties(cNode); - //addPseudoProperties if (includeSuperProperties) { ClassNode next = cNode.getSuperClass(); while (next != null) { @@ -356,6 +357,7 @@ public class ImmutableASTTransformation extends AbstractASTTransformation { return list; } + @Deprecated static void createConstructorOrdered(ClassNode cNode, List list) { final MapExpression argMap = new MapExpression(); final Parameter[] orderedParams = new Parameter[list.size()]; http://git-wip-us.apache.org/repos/asf/groovy/blob/82f1d4c4/src/spec/doc/core-metaprogramming.adoc ---------------------------------------------------------------------- diff --git a/src/spec/doc/core-metaprogramming.adoc b/src/spec/doc/core-metaprogramming.adoc index 94cca81..57f726f 100644 --- a/src/spec/doc/core-metaprogramming.adoc +++ b/src/spec/doc/core-metaprogramming.adoc @@ -1077,7 +1077,7 @@ annotations: include::{projectdir}/src/spec/test/CodeGenerationASTTransformsTest.groovy[tags=canonical_simple,indent=0] ---- -A similar immutable class can be generated using the <> AST transformation instead. +A similar immutable class can be generated using the <> meta-annotation instead. The `@Canonical` meta-annotation supports the configuration options found in the annotations it aggregates. See those annotations for more details. @@ -1698,24 +1698,57 @@ include::{projectdir}/src/spec/test/ClassDesignASTTransformsTest.groovy[tags=del [[xform-Immutable]] ===== `@groovy.transform.Immutable` -The `@Immutable` AST transformation simplifies the creation of immutable classes, that is to say classes for which -members are deemed immutable. For that, all you have to do is annotating the class like in the following example: +The `@Immutable` meta-annotation combines the following annotations: + +* <> +* <> +* <> +* <> +* <> +* <> + +The `@Immutable` meta-annotation simplifies the creation of immutable classes. Immutable classes are useful +since they are often easier to reason about and are inherently thread-safe. +See http://www.informit.com/store/effective-java-9780134685991[Effective Java, Minimize Mutability] for all the details +about how to achieve immutable classes in Java. The `@Immutable` meta-annotation does most of the things described +in _Effective Java_ for you automatically. +To use the meta-annotation, all you have to do is annotate the class like in the following example: [source,groovy] ---- include::{projectdir}/src/spec/test/ClassDesignASTTransformsTest.groovy[tags=immutable_simple,indent=0] ---- -Immutable classes generated with `@Immutable` are automatically made final. For a class to be immutable, you have to +One of the requirements for immutable classes is that there is no way to modify any state information within the class. +One requirement to achieve this is to use immutable classes for each property or alternatively perform special coding +such as defensive copy in and defensive copy out for any mutable properties within the constructors +and property getters. Between `@ImmutableBase`, `@MapConstructor` and `@TupleConstructor` properties +are either identified as immutable or the special coding for numerous known cases is handled automatically. +Various mechanisms are provided for you to extend the handled property types which are allowed. See +`@ImmutableBase` and `@KnownImmutable` for details. + +The results of applying `@Immutable` to a class are pretty similar to those of +applying the <> meta-annotation but the generated class will have extra +logic to handle immutability. You will observe this by, for instance, trying to modify a property +which will result in a `ReadOnlyPropertyException` being thrown since the backing field for the property +will have been automatically made final. + +The `@Immutable` meta-annotation supports the configuration options found in the annotations +it aggregates. See those annotations for more details. + +[[xform-ImmutableBase]] +===== `@groovy.transform.ImmutableBase` + +Immutable classes generated with `@ImmutableBase` are automatically made final. Also, the type of each property is checked +and various checks are made on the class, for example, public instance fields currently aren't allowed. + +For a class to be immutable, you have to make sure that properties are of an immutable type (primitive or boxed types), of a known-immutable type or another -class annotated with `@Immutable`. The effect of applying `@Immutable` to a class are pretty similar to those of -applying the <> AST transformation, but with an immutable class: automatic generation of -`toString`, `equals` and `hashCode` methods for example, but trying to modify a property would throw a `ReadOnlyPropertyException` -in that case. +class annotated with `@KnownImmutable` (which includes those annotated with the `@Immutable` meta-annotation). -Since `@Immutable` relies on a predefined list of known immutable classes (like `java.net.URI` or `java.lang.String` +Since `@ImmutableBase` relies on a predefined list of known immutable classes (like `java.net.URI` or `java.lang.String` and fails if you use a type which is not in that list, you are allowed to instruct the transformation that some types -are deemed immutable thanks to the following parameters: +are deemed immutable thanks to the following annotation attributes: [cols="1,1,2,3a",options="header"] |======================================================================= @@ -1738,6 +1771,17 @@ include::{projectdir}/src/spec/test/ClassDesignASTTransformsTest.groovy[tags=imm ---- |======================================================================= +If you deem a type as immutable and it isn't one of the ones automatically handled, then it is up to you +to correctly code that class to ensure immutability. + +[[xform-KnownImmutable]] +===== `@groovy.transform.KnownImmutable` + +The `@KnownImmutable` annotation isn't actually one that triggers any AST transformations. It is simply +a marker annotation. You can annotate your classes with the annotation (including Java classes) and they +will be recognized as acceptable types for members within an immutable class. This saves you having to +explicitly use the `knownImmutables` or `knownImmutableClasses` annotation attributes from `@ImmutableBase`. + [[xform-Memoized]] ===== `@groovy.transform.Memoized`