You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by pa...@apache.org on 2018/02/04 08:42:05 UTC

groovy git commit: improve doco for immutable-related annotations

Repository: groovy
Updated Branches:
  refs/heads/master bd205c955 -> a29598b1c


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/a29598b1
Tree: http://git-wip-us.apache.org/repos/asf/groovy/tree/a29598b1
Diff: http://git-wip-us.apache.org/repos/asf/groovy/diff/a29598b1

Branch: refs/heads/master
Commit: a29598b1c865aa5f8b155d19d2a52b66e7f97203
Parents: bd205c9
Author: paulk <pa...@asert.com.au>
Authored: Sun Feb 4 18:41:57 2018 +1000
Committer: paulk <pa...@asert.com.au>
Committed: Sun Feb 4 18:41:57 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/a29598b1/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<PropertyNode> getProperties(ClassNode cNode, boolean includeSuperProperties, boolean allProperties) {
         List<PropertyNode> 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<PropertyNode> list) {
         final MapExpression argMap = new MapExpression();
         final Parameter[] orderedParams = new Parameter[list.size()];

http://git-wip-us.apache.org/repos/asf/groovy/blob/a29598b1/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 <<x...@Immutable>> AST transformation instead.
+A similar immutable class can be generated using the <<x...@Immutable>> 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:
+
+* <<x...@ToString>>
+* <<x...@EqualsAndHashCode>>
+* <<x...@ImmutableBase>>
+* <<x...@TupleConstructor>>
+* <<x...@MapConstructor>>
+* <<x...@KnownImmutable>>
+
+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 <<x...@Canonical>> 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 <<x...@Canonical>> 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`