GROOVY-8300: @AutoFinal (asciidoc doco) (cherry picked from commit 9ea35d6)
Project: http://git-wip-us.apache.org/repos/asf/groovy/repo Commit: http://git-wip-us.apache.org/repos/asf/groovy/commit/5db12571 Tree: http://git-wip-us.apache.org/repos/asf/groovy/tree/5db12571 Diff: http://git-wip-us.apache.org/repos/asf/groovy/diff/5db12571 Branch: refs/heads/GROOVY_2_6_X Commit: 5db12571492b064fe4fdde679ee0ff1fc8469616 Parents: c7774a3 Author: paulk <pa...@asert.com.au> Authored: Wed Sep 13 20:35:27 2017 +0800 Committer: sunlan <sun...@apache.org> Committed: Wed Sep 13 20:50:23 2017 +0800 ---------------------------------------------------------------------- src/spec/doc/core-metaprogramming.adoc | 37 ++++++++++++++++ .../CompilerDirectivesASTTransformsTest.groovy | 46 ++++++++++++++++++++ 2 files changed, 83 insertions(+) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/groovy/blob/5db12571/src/spec/doc/core-metaprogramming.adoc ---------------------------------------------------------------------- diff --git a/src/spec/doc/core-metaprogramming.adoc b/src/spec/doc/core-metaprogramming.adoc index f2ffdc4..e18784a 100644 --- a/src/spec/doc/core-metaprogramming.adoc +++ b/src/spec/doc/core-metaprogramming.adoc @@ -2357,6 +2357,43 @@ The `@PackageScope` annotation is seldom used as part of normal Groovy conventio for factory methods that should be visible internally within a package or for methods or constructors provided for testing purposes, or when integrating with third-party libraries which require such visibility conventions. +[[xform-AutoFinal]] +===== `@groovy.transform.AutoFinal` + +The `@AutoFinal` annotation instructs the compiler to automatically insert the final modifier +in numerous places within the annotated node. If applied on a method (or constructor), the parameters +for that method (or constructor) will be marked as final. If applied on a class definition, the same +treatment will occur for all declared methods and constructors within that class. + +It is often considered bad practice to reassign parameters of a method or constructor with its body. +By adding the final modifier to all parameter declarations you can avoid this practice entirely. +Some programmers feel that adding final everywhere increases the amount of boilerplate code and makes the +method signatures somewhat noisy. An alternative might instead be to use a code review process or apply +a http://codenarc.org[codenarc] http://codenarc.sourceforge.net/codenarc-rules-convention.html#ParameterReassignment[rule] +to give warnings if that practice is observed but these alternatives might lead to delayed feedback during +quality checking rather than within the IDE or during compilation. The `@AutoFinal` annotation aims to +maximise compiler/IDE feedback while retaining succinct code with minimum boilerplate noise. + +The following example illustrates applying the annotation at the class level: + +[source,groovy] +---- +include::{projectdir}/src/spec/test/CompilerDirectivesASTTransformsTest.groovy[tags=autofinal_class,indent=0] +---- + +In this example, the two parameters for the constructor and the single parameter for +both the `fullname` and `greeting` methods will be final. Attempts to modify those parameters within the +constructor or method bodies will be flagged by the compiler. + +The following example illustrates applying the annotation at the method level: + +[source,groovy] +---- +include::{projectdir}/src/spec/test/CompilerDirectivesASTTransformsTest.groovy[tags=autofinal_method,indent=0] +---- + +Here, the `add` method will have final parameters but the `mult` method will remain unchanged. + [[xform-AnnotationCollector]] ===== `@groovy.transform.AnnotationCollector` http://git-wip-us.apache.org/repos/asf/groovy/blob/5db12571/src/spec/test/CompilerDirectivesASTTransformsTest.groovy ---------------------------------------------------------------------- diff --git a/src/spec/test/CompilerDirectivesASTTransformsTest.groovy b/src/spec/test/CompilerDirectivesASTTransformsTest.groovy index 29ccd9f..8e72851 100644 --- a/src/spec/test/CompilerDirectivesASTTransformsTest.groovy +++ b/src/spec/test/CompilerDirectivesASTTransformsTest.groovy @@ -96,6 +96,52 @@ new MyScript().run() ''' } + void testAutoFinalClass() { + assertScript ''' +// tag::autofinal_class[] +import groovy.transform.AutoFinal + +@AutoFinal +class Person { + private String first, last + + Person(String first, String last) { + this.first = first + this.last = last + } + + String fullName(String separator) { + "$first$separator$last" + } + + String greeting(String salutation) { + "$salutation, $first" + } +} +// end::autofinal_class[] +def john = new Person('John', 'Smith') +assert john.fullName(' ') == 'John Smith' +assert john.greeting('Hello') == 'Hello, John' +''' + } + + void testAutoFinalMethod() { + assertScript ''' +import groovy.transform.AutoFinal +// tag::autofinal_method[] +class Calc { + @AutoFinal + int add(int a, int b) { a + b } + + int mult(int a, int b) { a * b } +} +// end::autofinal_method[] +def calc = new Calc() +assert calc.add(3, 6) == 9 +assert calc.mult(3, 6) == 18 +''' + } + void testPackageScope() { assertScript '''import java.lang.reflect.Modifier // tag::packagescope_property[]