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 2016/03/02 20:25:02 UTC

[2/2] groovy git commit: More example code to show usage of annotations based on MrHaki's Groovy Goodness blog posts (closes #275, closes #271)

More example code to show usage of annotations based on MrHaki's Groovy Goodness blog posts (closes #275, closes #271)

* More examples for API doc readers to understand how to use the annotations.
* Used HTML entity code for @-symbol instead of enclosing in {@code...} block.


Project: http://git-wip-us.apache.org/repos/asf/groovy/repo
Commit: http://git-wip-us.apache.org/repos/asf/groovy/commit/120aee12
Tree: http://git-wip-us.apache.org/repos/asf/groovy/tree/120aee12
Diff: http://git-wip-us.apache.org/repos/asf/groovy/diff/120aee12

Branch: refs/heads/master
Commit: 120aee1226f8dbe2b7eb42ea77f9239e520c7103
Parents: 80d1364
Author: Hubert Klein Ikkink <h....@gmail.com>
Authored: Wed Mar 2 15:44:52 2016 +0100
Committer: pascalschumacher <pa...@gmx.net>
Committed: Wed Mar 2 20:15:58 2016 +0100

----------------------------------------------------------------------
 .../groovy/transform/AnnotationCollector.java   | 94 ++++++++++++++++++++
 src/main/groovy/transform/BaseScript.java       | 56 ++++++++++++
 .../groovy/transform/EqualsAndHashCode.java     | 25 ++++++
 src/main/groovy/transform/Immutable.java        | 44 +++++++++
 src/main/groovy/transform/ToString.java         | 16 ++--
 src/main/groovy/transform/TupleConstructor.java | 10 +--
 6 files changed, 232 insertions(+), 13 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/groovy/blob/120aee12/src/main/groovy/transform/AnnotationCollector.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/transform/AnnotationCollector.java b/src/main/groovy/transform/AnnotationCollector.java
index 01a9b73..23a7335 100644
--- a/src/main/groovy/transform/AnnotationCollector.java
+++ b/src/main/groovy/transform/AnnotationCollector.java
@@ -73,6 +73,100 @@ import java.lang.annotation.Target;
  * EqualsAndHashCode.
  * If both ways are combined, then the list overwrites annotation usage.
  * NOTE: The aliasing does not support aliasing of aliased annotations. 
+ * <p>More examples:</p>
+ * <pre>
+ * //--------------------------------------------------------------------------
+ * &#64;AnnotationCollector([EqualsAndHashCode, ToString])
+ * &#64;interface Simple {}
+ *
+ *
+ * &#64;Simple
+ * class User {
+ *     String username
+ *     int age
+ * }
+ *
+ * def user = new User(username: 'mrhaki', age: 39)
+ * assert user.toString() == 'User(mrhaki, 39)'
+ *
+ * // We still have 2 annotations:
+ * assert User.class.annotations.size() == 2
+ *
+ *
+ * // We can use the attributes from the 
+ * // grouped annotations.
+ * &#64;Simple(excludes = 'street') 
+ * class Address {
+ *     String street, town
+ * }
+ *
+ * def address = new Address(street: 'Evergreen Terrace', town: 'Springfield') 
+ * assert address.toString() == 'Address(Springfield)'
+ * </pre>
+ * <pre>
+ * //--------------------------------------------------------------------------
+ * // Use a custom processor to handle attributes.
+ * import org.codehaus.groovy.transform.*
+ * import org.codehaus.groovy.ast.*
+ * import org.codehaus.groovy.control.*
+ *
+ * class SimpleProcessor extends AnnotationCollectorTransform {
+ *
+ *     public List&lt;AnnotationNode&gt; visit(AnnotationNode collector, 
+ *                                       AnnotationNode aliasAnnotationUsage, 
+ *                                       AnnotatedNode aliasAnnotated, 
+ *                                       SourceUnit source) {
+ *
+ *         // Get attributes and attribute value for dontUse.
+ *         def attributes = aliasAnnotationUsage.getMembers()
+ *         def dontUse = attributes.get('dontUse')
+ *         attributes.remove('dontUse')
+ *
+ *         if (dontUse) {
+ *             // Assign value of dontUse to excludes attributes.
+ *             aliasAnnotationUsage.addMember("excludes", dontUse)
+ *         }
+ *
+ *         super.visit(collector, aliasAnnotationUsage, aliasAnnotated, source)
+ *     }
+ *
+ * }
+ *
+ * new GroovyShell(this.class.classLoader).evaluate '''
+ * import groovy.transform.*
+ *
+ * &#64;AnnotationCollector(value = [EqualsAndHashCode, ToString], processor = 'SimpleProcessor')
+ * &#64;interface Simple {}
+ *
+ *
+ * &#64;Simple(dontUse = 'age')
+ * class User {
+ *     String username
+ *     int age
+ * }
+ *
+ * def user = new User(username: 'mrhaki', age: 39)
+ * assert user.toString() == 'User(mrhaki)'
+ * '''
+ * </pre>
+ * <pre>
+ * //--------------------------------------------------------------------------
+ * // Use AnnotationCollector as last annotation to group the
+ * // previous annotations.
+ * &#64;EqualsAndHashCode
+ * &#64;ToString
+ * &#64;AnnotationCollector
+ * &#64;interface Simple {}
+ *
+ *
+ * &#64;Simple
+ * class User {
+ *     String username
+ * }
+ *
+ * def user = new User(username: 'mrhaki')
+ * assert user.toString() == 'User(mrhaki)'
+ * </pre>
  * 
  * @author <a href="mailto:blackdrag@gmx.org">Jochen "blackdrag" Theodorou</a>
  * @see org.codehaus.groovy.transform.AnnotationCollectorTransform

http://git-wip-us.apache.org/repos/asf/groovy/blob/120aee12/src/main/groovy/transform/BaseScript.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/transform/BaseScript.java b/src/main/groovy/transform/BaseScript.java
index 5eb3a7a..af3e594 100644
--- a/src/main/groovy/transform/BaseScript.java
+++ b/src/main/groovy/transform/BaseScript.java
@@ -84,6 +84,62 @@ import java.lang.annotation.Target;
  * Note that while you can declare arguments for the script body's method, as
  * the AST is currently implemented they are not accessible in the script body code.
  * </p>
+ * <p>More examples:</p>
+ * <pre>
+ * // Simple Car class to save state and distance.
+ * class Car {
+ *     String state
+ *     Long distance = 0
+ * }
+ *
+ * // Custom Script with methods that change the Car's state.
+ * // The Car object is passed via the binding.
+ * abstract class CarScript extends Script {
+ *     def start() {
+ *         this.binding.car.state = 'started'
+ *     }
+ *
+ *     def stop() {
+ *         this.binding.car.state = 'stopped'
+ *     }
+ *
+ *     def drive(distance) {
+ *         this.binding.car.distance += distance
+ *     }
+ * }
+ *
+ *
+ * // Define Car object here, so we can use it in assertions later on.
+ * def car = new Car()
+ * // Add to script binding (CarScript references this.binding.car).
+ * def binding = new Binding(car: car)
+ *
+ * // Configure the GroovyShell.
+ * def shell = new GroovyShell(this.class.classLoader, binding)
+ *
+ * // Simple DSL to start, drive and stop the car.
+ * // The methods are defined in the CarScript class.
+ * def carDsl = '''
+ * start()
+ * drive 20
+ * stop()
+ * '''
+ *
+ *
+ * // Run DSL script.
+ * shell.evaluate """
+ * // Use BaseScript annotation to set script
+ * // for evaluating the DSL.
+ * &#64;groovy.transform.BaseScript CarScript carScript
+ *
+ * $carDsl
+ * """
+ *
+ * // Checks to see that Car object has changed.
+ * assert car.distance == 20
+ * assert car.state == 'stopped'
+ * </pre>
+ * 
  * @author Paul King
  * @author Vladimir Orany
  * @author Jim White

http://git-wip-us.apache.org/repos/asf/groovy/blob/120aee12/src/main/groovy/transform/EqualsAndHashCode.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/transform/EqualsAndHashCode.java b/src/main/groovy/transform/EqualsAndHashCode.java
index 51bd1b5..2c75279 100644
--- a/src/main/groovy/transform/EqualsAndHashCode.java
+++ b/src/main/groovy/transform/EqualsAndHashCode.java
@@ -192,6 +192,31 @@ import java.lang.annotation.Target;
  * infinite recursion but the algorithm used may not suit your scenario, so use with caution if
  * you have such structures.
  * A future version of this transform may better handle some additional recursive scenarios.
+ * <p>More examples:</p>
+ * <pre>
+ * import groovy.transform.EqualsAndHashCode
+ *
+ * &#64;EqualsAndHashCode(includeFields=true)
+ * class User {
+ *     String name
+ *     boolean active
+ *     List likes
+ *     private int age = 37
+ * }
+ *
+ * def user = new User(name: 'mrhaki', active: false, likes: ['Groovy', 'Java'])
+ * def mrhaki = new User(name: 'mrhaki', likes: ['Groovy', 'Java'])
+ * def hubert = new User(name: 'Hubert Klein Ikkink', likes: ['Groovy', 'Java'])
+ *
+ * assert user == mrhaki
+ * assert mrhaki != hubert
+ *
+ * Set users = new HashSet()
+ * users.add user
+ * users.add mrhaki
+ * users.add hubert
+ * assert users.size() == 2
+ * </pre>
  *
  * @see org.codehaus.groovy.util.HashCodeHelper
  * @author Paul King

http://git-wip-us.apache.org/repos/asf/groovy/blob/120aee12/src/main/groovy/transform/Immutable.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/transform/Immutable.java b/src/main/groovy/transform/Immutable.java
index 0cbffdc..314abbc 100644
--- a/src/main/groovy/transform/Immutable.java
+++ b/src/main/groovy/transform/Immutable.java
@@ -122,6 +122,50 @@ import java.lang.annotation.Target;
  * has type {@code LinkedHashMap} or if there is a single Map, AbstractMap or HashMap property.
  * </li>
  * </ul>
+ * <p>More examples:</p>
+ --------------------------------------------------------------------------------
+ * <pre>
+ * import groovy.transform.*
+ *
+ * &#64;Canonical
+ * class Building {
+ *     String name
+ *     int floors
+ *     boolean officeSpace
+ * }
+ *
+ * // Constructors are added.
+ * def officeSpace = new Building('Initech office', 1, true)
+ *
+ * // toString() added.
+ * assert officeSpace.toString() == 'Building(Initech office, 1, true)'
+ *
+ * // Default values are used if constructor
+ * // arguments are not assigned.
+ * def theOffice = new Building('Wernham Hogg Paper Company')
+ * assert theOffice.floors == 0
+ * theOffice.officeSpace = true
+ *
+ * def anotherOfficeSpace = new Building(name: 'Initech office', floors: 1, officeSpace: true)
+ *
+ * // equals() method is added.
+ * assert anotherOfficeSpace == officeSpace
+ *
+ * // equals() and hashCode() are added, so duplicate is not in Set.
+ * def offices = [officeSpace, anotherOfficeSpace, theOffice] as Set  
+ * assert offices.size() == 2 
+ * assert offices.name.join(',') == 'Initech office,Wernham Hogg Paper Company'
+ *
+ * &#64;Canonical
+ * &#64;ToString(excludes='age')  // Customize one of the transformations.
+ * class Person {
+ *     String name
+ *     int age
+ * }
+ *
+ * def mrhaki = new Person('mrhaki', 37)
+ * assert mrhaki.toString() == 'Person(mrhaki)'
+ * </pre>
  *
  * @author Paul King
  * @author Andre Steingress

http://git-wip-us.apache.org/repos/asf/groovy/blob/120aee12/src/main/groovy/transform/ToString.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/transform/ToString.java b/src/main/groovy/transform/ToString.java
index 342a363..1d56f5f 100644
--- a/src/main/groovy/transform/ToString.java
+++ b/src/main/groovy/transform/ToString.java
@@ -134,7 +134,7 @@ import java.lang.annotation.Target;
  * // includeNames to output the names of the properties.
  * import groovy.transform.ToString
  *
- * {@code @ToString(includeNames=true)}
+ * &#64;@ToString(includeNames=true)
  * class Person {
  *     String name
  *     List likes
@@ -150,7 +150,7 @@ import java.lang.annotation.Target;
  * // includeFields to not only output properties, but also field values.
  * import groovy.transform.ToString
  *
- * {@code @ToString(includeNames=true, includeFields=true)}
+ * &#64;ToString(includeNames=true, includeFields=true)
  * class Person {
  *     String name
  *     List likes
@@ -166,14 +166,14 @@ import java.lang.annotation.Target;
  * // Use includeSuper to include properties from super class in output.
  * import groovy.transform.ToString
  *
- * {@code @ToString(includeNames=true)}
+ * &#64;ToString(includeNames=true)
  * class Person {
  *     String name
  *     List likes
  *     private boolean active = false
  * }
  *
- * {@code @ToString(includeSuper=true, includeNames=true)}
+ * &#64;ToString(includeSuper=true, includeNames=true)
  * class Student extends Person {
  *     List courses
  * }
@@ -187,7 +187,7 @@ import java.lang.annotation.Target;
  * // excludes active field and likes property from output
  * import groovy.transform.ToString
  *
- * {@code @ToString(includeNames=true, includeFields=true, excludes='active,likes')}
+ * &#64;ToString(includeNames=true, includeFields=true, excludes='active,likes')
  * class Person {
  *     String name
  *     List likes
@@ -205,7 +205,7 @@ import java.lang.annotation.Target;
  *
  * import groovy.transform.*
  *
- * {@code @ToString(includePackage=false)}
+ * &#64;ToString(includePackage=false)
  * class Course {
  *     String title
  *     Integer maxAttendees
@@ -222,7 +222,7 @@ import java.lang.annotation.Target;
  *
  * import groovy.transform.*
  *
- * {@code @ToString(ignoreNulls=true)}
+ * &#64;ToString(ignoreNulls=true)
  * class Course {
  *     String title
  *     Integer maxAttendees
@@ -239,7 +239,7 @@ import java.lang.annotation.Target;
  *
  * import groovy.transform.*
  *
- * {@code @ToString(cache=true)}
+ * &#64;@ToString(cache=true)
  * class Course {
  *     String title
  *     Integer maxAttendees

http://git-wip-us.apache.org/repos/asf/groovy/blob/120aee12/src/main/groovy/transform/TupleConstructor.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/transform/TupleConstructor.java b/src/main/groovy/transform/TupleConstructor.java
index 2d7ac9d..e472667 100644
--- a/src/main/groovy/transform/TupleConstructor.java
+++ b/src/main/groovy/transform/TupleConstructor.java
@@ -60,7 +60,7 @@ import java.lang.annotation.Target;
  * //--------------------------------------------------------------------------
  * import groovy.transform.TupleConstructor
  *
- * {@code @TupleConstructor()}
+ * &#64;TupleConstructor()
  * class Person {
  *     String name
  *     List likes
@@ -82,7 +82,7 @@ import java.lang.annotation.Target;
  * // includeFields in the constructor creation.
  * import groovy.transform.TupleConstructor
  *
- * {@code @TupleConstructor(includeFields=true)}
+ * &#64;TupleConstructor(includeFields=true)
  * class Person {
  *     String name
  *     List likes
@@ -103,7 +103,7 @@ import java.lang.annotation.Target;
  * // even if we define our own constructors.
  * import groovy.transform.TupleConstructor
  *
- * {@code @TupleConstructor(force=true)}
+ * &#64;TupleConstructor(force=true)
  * class Person {
  *     String name
  *     List likes
@@ -131,7 +131,7 @@ import java.lang.annotation.Target;
  * // include properties and fields from super class.
  * import groovy.transform.TupleConstructor
  *
- * {@code @TupleConstructor(includeFields=true)}
+ * &#64;TupleConstructor(includeFields=true)
  * class Person {
  *     String name
  *     List likes
@@ -140,7 +140,7 @@ import java.lang.annotation.Target;
  *     boolean isActivated() { active }
  * }
  *
- * {@code @TupleConstructor(callSuper=true, includeSuperProperties=true, includeSuperFields=true)}
+ * &#64;TupleConstructor(callSuper=true, includeSuperProperties=true, includeSuperFields=true)
  * class Student extends Person {
  *     List courses
  * }