first cut doco for @Macro
Project: http://git-wip-us.apache.org/repos/asf/groovy/repo Commit: http://git-wip-us.apache.org/repos/asf/groovy/commit/fcdc0e9e Tree: http://git-wip-us.apache.org/repos/asf/groovy/tree/fcdc0e9e Diff: http://git-wip-us.apache.org/repos/asf/groovy/diff/fcdc0e9e Branch: refs/heads/GROOVY_2_6_X Commit: fcdc0e9e8196427cc40792cc9010ddfcde999748 Parents: a65e93a Author: Paul King <[email protected]> Authored: Sun May 27 12:44:52 2018 +1000 Committer: Paul King <[email protected]> Committed: Sun May 27 12:51:22 2018 +1000 ---------------------------------------------------------------------- src/spec/doc/core-metaprogramming.adoc | 43 +++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/groovy/blob/fcdc0e9e/src/spec/doc/core-metaprogramming.adoc ---------------------------------------------------------------------- diff --git a/src/spec/doc/core-metaprogramming.adoc b/src/spec/doc/core-metaprogramming.adoc index 0247589..32ac759 100644 --- a/src/spec/doc/core-metaprogramming.adoc +++ b/src/spec/doc/core-metaprogramming.adoc @@ -3238,6 +3238,49 @@ IMPORTANT: Notice that we're using `@CompileDynamic`. That's because the way we were actually implementing it. So if you were using `@CompileStatic` it will complain because an implementation of an abstract class can't be another different class. +===== @Macro methods + +You have seen that by using `macro` you can save yourself a lot of work but you might wonder where +that method came from. You didn't declare it or static import it. You can think of it as a special +global method (or if you prefer, a method on every `Object`). This is much like how the `println` +extension method is defined. But unlike `println` which becomes a method selected for execution +later in the compilation process, `macro` expansion is done early in the compilation process. +The declaration of `macro` as one of the available methods for this early expansion is done +by annotating a `macro` method definition with the `@Macro` annotation and making that method +available using a similar mechanism for extension modules. Such methods are known as _macro_ methods +and the good news is you can define your own. + +To define your own macro method, create a class in a similar way to an extension module and +add a method such as: + +[source,groovy] +---- +public class ExampleMacroMethods { + + @Macro + public static Expression safe(MacroContext macroContext, MethodCallExpression callExpression) { + return ternaryX( + notNullX(callExpression.getObjectExpression()), + callExpression, + constX(null) + ); + } + ... +} +---- + +Now you would register this as an extension module using a `org.codehaus.groovy.runtime.ExtensionModule` +file within the `META-INF/groovy` directory. + +Now, assuming that the class and meta info file are on your classpath, you can use the +macro method in the following way: + +[source,groovy] +---- +def nullObject = null +assert null == safe(safe(nullObject.hashcode()).toString()) +---- + ==== Testing AST transformations ===== Separating source trees
