http://git-wip-us.apache.org/repos/asf/groovy/blob/10110145/src/main/groovy/org/codehaus/groovy/transform/tailrec/TailRecursiveASTTransformation.groovy
----------------------------------------------------------------------
diff --git 
a/src/main/groovy/org/codehaus/groovy/transform/tailrec/TailRecursiveASTTransformation.groovy
 
b/src/main/groovy/org/codehaus/groovy/transform/tailrec/TailRecursiveASTTransformation.groovy
new file mode 100644
index 0000000..0605f18
--- /dev/null
+++ 
b/src/main/groovy/org/codehaus/groovy/transform/tailrec/TailRecursiveASTTransformation.groovy
@@ -0,0 +1,261 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.codehaus.groovy.transform.tailrec
+
+import groovy.transform.CompileStatic
+import groovy.transform.Memoized
+import groovy.transform.TailRecursive
+import org.codehaus.groovy.ast.ASTNode
+import org.codehaus.groovy.ast.AnnotationNode
+import org.codehaus.groovy.ast.ClassHelper
+import org.codehaus.groovy.ast.ClassNode
+import org.codehaus.groovy.ast.MethodNode
+import org.codehaus.groovy.ast.Parameter
+import org.codehaus.groovy.ast.expr.Expression
+import org.codehaus.groovy.ast.expr.MethodCallExpression
+import org.codehaus.groovy.ast.expr.StaticMethodCallExpression
+import org.codehaus.groovy.ast.expr.TernaryExpression
+import org.codehaus.groovy.ast.expr.VariableExpression
+import org.codehaus.groovy.ast.stmt.BlockStatement
+import org.codehaus.groovy.ast.stmt.ReturnStatement
+import org.codehaus.groovy.ast.stmt.Statement
+import org.codehaus.groovy.classgen.ReturnAdder
+import org.codehaus.groovy.classgen.VariableScopeVisitor
+import org.codehaus.groovy.control.CompilePhase
+import org.codehaus.groovy.control.SourceUnit
+import org.codehaus.groovy.transform.AbstractASTTransformation
+import org.codehaus.groovy.transform.GroovyASTTransformation
+
+/**
+ * Handles generation of code for the @TailRecursive annotation.
+ *
+ * It's doing its work in the earliest possible compile phase
+ *
+ * @author Johannes Link
+ */
+@CompileStatic
+@GroovyASTTransformation(phase = CompilePhase.SEMANTIC_ANALYSIS)
+class TailRecursiveASTTransformation extends AbstractASTTransformation {
+
+    private static final Class MY_CLASS = TailRecursive.class;
+    private static final ClassNode MY_TYPE = new ClassNode(MY_CLASS);
+    static final String MY_TYPE_NAME = "@" + MY_TYPE.getNameWithoutPackage()
+    private HasRecursiveCalls hasRecursiveCalls = new HasRecursiveCalls()
+    private TernaryToIfStatementConverter ternaryToIfStatement = new 
TernaryToIfStatementConverter()
+
+
+    @Override
+    public void visit(ASTNode[] nodes, SourceUnit source) {
+        init(nodes, source);
+
+        MethodNode method = nodes[1] as MethodNode
+
+        if (method.isAbstract()) {
+            addError("Annotation " + MY_TYPE_NAME + " cannot be used for 
abstract methods.", method);
+            return;
+        }
+
+        if (hasAnnotation(method, ClassHelper.make(Memoized))) {
+            ClassNode memoizedClassNode = ClassHelper.make(Memoized)
+            for (AnnotationNode annotationNode in method.annotations) {
+                if (annotationNode.classNode == MY_TYPE)
+                    break
+                if (annotationNode.classNode == memoizedClassNode) {
+                    addError("Annotation " + MY_TYPE_NAME + " must be placed 
before annotation @Memoized.", annotationNode)
+                    return
+                }
+            }
+        }
+
+        if (!hasRecursiveMethodCalls(method)) {
+            AnnotationNode annotationNode = 
method.getAnnotations(ClassHelper.make(TailRecursive))[0]
+            addError("No recursive calls detected. You must remove annotation 
" + MY_TYPE_NAME + ".", annotationNode)
+            return;
+        }
+
+        transformToIteration(method, source)
+        ensureAllRecursiveCallsHaveBeenTransformed(method)
+    }
+
+    private boolean hasAnnotation(MethodNode methodNode, ClassNode annotation) 
{
+        List annots = methodNode.getAnnotations(annotation);
+        return (annots != null && annots.size() > 0);
+    }
+
+
+    private void transformToIteration(MethodNode method, SourceUnit source) {
+        if (method.isVoidMethod()) {
+            transformVoidMethodToIteration(method, source)
+        } else {
+            transformNonVoidMethodToIteration(method, source)
+        }
+    }
+
+    private void transformVoidMethodToIteration(MethodNode method, SourceUnit 
source) {
+        addError("Void methods are not supported by @TailRecursive yet.", 
method)
+    }
+
+    private void transformNonVoidMethodToIteration(MethodNode method, 
SourceUnit source) {
+        addMissingDefaultReturnStatement(method)
+        replaceReturnsWithTernariesToIfStatements(method)
+        wrapMethodBodyWithWhileLoop(method)
+
+        Map<String, Map> nameAndTypeMapping = name2VariableMappingFor(method)
+        replaceAllAccessToParams(method, nameAndTypeMapping)
+        addLocalVariablesForAllParameters(method, nameAndTypeMapping) //must 
happen after replacing access to params
+
+        Map<Integer, Map> positionMapping = position2VariableMappingFor(method)
+        replaceAllRecursiveReturnsWithIteration(method, positionMapping)
+        repairVariableScopes(source, method)
+    }
+
+    private void repairVariableScopes(SourceUnit source, MethodNode method) {
+        new VariableScopeVisitor(source).visitClass(method.declaringClass)
+    }
+
+    private void replaceReturnsWithTernariesToIfStatements(MethodNode method) {
+        Closure<Boolean> whenReturnWithTernary = { ASTNode node ->
+            if (!(node instanceof ReturnStatement)) {
+                return false
+            }
+            return (((ReturnStatement) node).expression instanceof 
TernaryExpression)
+        }
+        Closure<Statement> replaceWithIfStatement = { ReturnStatement 
statement ->
+            ternaryToIfStatement.convert(statement)
+        }
+        StatementReplacer replacer = new StatementReplacer(when: 
whenReturnWithTernary, replaceWith: replaceWithIfStatement)
+        replacer.replaceIn(method.code)
+
+    }
+
+    private void addLocalVariablesForAllParameters(MethodNode method, 
Map<String, Map> nameAndTypeMapping) {
+        BlockStatement code = method.code as BlockStatement
+        nameAndTypeMapping.each { String paramName, Map localNameAndType ->
+            code.statements.add(0, AstHelper.createVariableDefinition(
+                    (String) localNameAndType['name'],
+                    (ClassNode) localNameAndType['type'],
+                    new VariableExpression(paramName, (ClassNode) 
localNameAndType['type'])
+            ))
+        }
+    }
+
+    private void replaceAllAccessToParams(MethodNode method, Map<String, Map> 
nameAndTypeMapping) {
+        new VariableAccessReplacer(nameAndTypeMapping: 
nameAndTypeMapping).replaceIn(method.code)
+    }
+
+    // Public b/c there are tests for this method
+    Map<String, Map> name2VariableMappingFor(MethodNode method) {
+        Map<String, Map> nameAndTypeMapping = [:]
+        method.parameters.each { Parameter param ->
+            String paramName = param.name
+            ClassNode paramType = param.type as ClassNode
+            String iterationVariableName = iterationVariableName(paramName)
+            nameAndTypeMapping[paramName] = [name: iterationVariableName, 
type: paramType]
+        }
+        return nameAndTypeMapping
+    }
+
+    // Public b/c there are tests for this method
+    Map<Integer, Map> position2VariableMappingFor(MethodNode method) {
+        Map<Integer, Map> positionMapping = [:]
+        method.parameters.eachWithIndex { Parameter param, int index ->
+            String paramName = param.name
+            ClassNode paramType = param.type as ClassNode
+            String iterationVariableName = 
this.iterationVariableName(paramName)
+            positionMapping[index] = [name: iterationVariableName, type: 
paramType]
+        }
+        return positionMapping
+    }
+
+    private String iterationVariableName(String paramName) {
+        '_' + paramName + '_'
+    }
+
+    private void replaceAllRecursiveReturnsWithIteration(MethodNode method, 
Map positionMapping) {
+        replaceRecursiveReturnsOutsideClosures(method, positionMapping)
+        replaceRecursiveReturnsInsideClosures(method, positionMapping)
+    }
+
+    private void replaceRecursiveReturnsOutsideClosures(MethodNode method, 
Map<Integer, Map> positionMapping) {
+        Closure<Boolean> whenRecursiveReturn = { Statement statement, boolean 
inClosure ->
+            if (inClosure)
+                return false
+            if (!(statement instanceof ReturnStatement)) {
+                return false
+            }
+            Expression inner = ((ReturnStatement) statement).expression
+            if (!(inner instanceof MethodCallExpression) && !(inner instanceof 
StaticMethodCallExpression)) {
+                return false
+            }
+            return isRecursiveIn(inner, method)
+        }
+        Closure<Statement> replaceWithContinueBlock = { ReturnStatement 
statement ->
+            new ReturnStatementToIterationConverter().convert(statement, 
positionMapping)
+        }
+        def replacer = new StatementReplacer(when: whenRecursiveReturn, 
replaceWith: replaceWithContinueBlock)
+        replacer.replaceIn(method.code)
+    }
+
+    private void replaceRecursiveReturnsInsideClosures(MethodNode method, 
Map<Integer, Map> positionMapping) {
+        Closure<Boolean> whenRecursiveReturn = { Statement statement, boolean 
inClosure ->
+            if (!inClosure)
+                return false
+            if (!(statement instanceof ReturnStatement)) {
+                return false
+            }
+            Expression inner = ((ReturnStatement )statement).expression
+            if (!(inner instanceof MethodCallExpression) && !(inner instanceof 
StaticMethodCallExpression)) {
+                return false
+            }
+            return isRecursiveIn(inner, method)
+        }
+        Closure<Statement> replaceWithThrowLoopException = { ReturnStatement 
statement ->
+            new ReturnStatementToIterationConverter(recurStatement: 
AstHelper.recurByThrowStatement()).convert(statement, positionMapping)
+        }
+        StatementReplacer replacer = new StatementReplacer(when: 
whenRecursiveReturn, replaceWith: replaceWithThrowLoopException)
+        replacer.replaceIn(method.code)
+    }
+
+    private void wrapMethodBodyWithWhileLoop(MethodNode method) {
+        new InWhileLoopWrapper().wrap(method)
+    }
+
+    private void addMissingDefaultReturnStatement(MethodNode method) {
+        new ReturnAdder().visitMethod(method)
+        new ReturnAdderForClosures().visitMethod(method)
+    }
+
+    private void ensureAllRecursiveCallsHaveBeenTransformed(MethodNode method) 
{
+        List<Expression> remainingRecursiveCalls = new 
CollectRecursiveCalls().collect(method)
+        for(Expression expression : remainingRecursiveCalls) {
+            addError("Recursive call could not be transformed by 
@TailRecursive. Maybe it's not a tail call.", expression)
+        }
+    }
+
+    private boolean hasRecursiveMethodCalls(MethodNode method) {
+        hasRecursiveCalls.test(method)
+    }
+
+    private boolean isRecursiveIn(Expression methodCall, MethodNode method) {
+        if (methodCall instanceof MethodCallExpression)
+            return new RecursivenessTester().isRecursive(method, 
(MethodCallExpression) methodCall)
+        if (methodCall instanceof StaticMethodCallExpression)
+            return new RecursivenessTester().isRecursive(method, 
(StaticMethodCallExpression) methodCall)
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/groovy/blob/10110145/src/main/groovy/org/codehaus/groovy/transform/tailrec/TernaryToIfStatementConverter.groovy
----------------------------------------------------------------------
diff --git 
a/src/main/groovy/org/codehaus/groovy/transform/tailrec/TernaryToIfStatementConverter.groovy
 
b/src/main/groovy/org/codehaus/groovy/transform/tailrec/TernaryToIfStatementConverter.groovy
new file mode 100644
index 0000000..c47e1d2
--- /dev/null
+++ 
b/src/main/groovy/org/codehaus/groovy/transform/tailrec/TernaryToIfStatementConverter.groovy
@@ -0,0 +1,42 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.codehaus.groovy.transform.tailrec
+
+import groovy.transform.CompileStatic
+import org.codehaus.groovy.ast.expr.TernaryExpression
+import org.codehaus.groovy.ast.stmt.IfStatement
+import org.codehaus.groovy.ast.stmt.ReturnStatement
+import org.codehaus.groovy.ast.stmt.Statement
+
+/**
+ * Since a ternary statement has more than one exit point tail-recursiveness 
testing cannot be easily done.
+ * Therefore this class translates a ternary statement (or Elvis operator) 
into the equivalent if-else statement.
+ *
+ * @author Johannes Link
+ */
+@CompileStatic
+class TernaryToIfStatementConverter {
+
+    Statement convert(ReturnStatement statementWithInnerTernaryExpression) {
+        if (!(statementWithInnerTernaryExpression.expression instanceof 
TernaryExpression))
+            return statementWithInnerTernaryExpression
+        TernaryExpression ternary = 
statementWithInnerTernaryExpression.expression as TernaryExpression
+        return new IfStatement(ternary.booleanExpression, new 
ReturnStatement(ternary.trueExpression), new 
ReturnStatement(ternary.falseExpression))
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/groovy/blob/10110145/src/main/groovy/org/codehaus/groovy/transform/tailrec/VariableAccessReplacer.groovy
----------------------------------------------------------------------
diff --git 
a/src/main/groovy/org/codehaus/groovy/transform/tailrec/VariableAccessReplacer.groovy
 
b/src/main/groovy/org/codehaus/groovy/transform/tailrec/VariableAccessReplacer.groovy
new file mode 100644
index 0000000..d62dc46
--- /dev/null
+++ 
b/src/main/groovy/org/codehaus/groovy/transform/tailrec/VariableAccessReplacer.groovy
@@ -0,0 +1,73 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.codehaus.groovy.transform.tailrec
+
+import groovy.transform.CompileStatic
+import org.codehaus.groovy.ast.ASTNode
+import org.codehaus.groovy.ast.expr.VariableExpression
+
+/**
+ * Replace all access to variables and args by new variables.
+ * The variable names to replace as well as their replacement name and type 
have to be configured
+ * in nameAndTypeMapping before calling replaceIn().
+ *
+ * The VariableReplacedListener can be set if clients want to react to 
variable replacement.
+ *
+ * @author Johannes Link
+ */
+@CompileStatic
+class VariableAccessReplacer {
+
+    /**
+     * Nested map of variable accesses to replace
+     * e.g.: [
+     *          'varToReplace': [name: 'newVar', type: TypeOfVar],
+     *          'varToReplace2': [name: 'newVar2', type: TypeOfVar2],
+     *       ]
+     */
+    Map<String, Map> nameAndTypeMapping = [:]
+
+    VariableReplacedListener listener = VariableReplacedListener.NULL
+
+    void replaceIn(ASTNode root) {
+        Closure<Boolean> whenParam = { VariableExpression expr ->
+            return nameAndTypeMapping.containsKey(expr.name)
+        }
+        Closure<VariableExpression> replaceWithLocalVariable = { 
VariableExpression expr ->
+            Map nameAndType = nameAndTypeMapping[expr.name]
+            VariableExpression newVar = 
AstHelper.createVariableReference(nameAndType)
+            listener.variableReplaced(expr, newVar)
+            return newVar
+        }
+        new VariableExpressionReplacer(when: whenParam, replaceWith: 
replaceWithLocalVariable).replaceIn(root)
+    }
+
+}
+
+@CompileStatic
+interface VariableReplacedListener {
+    void variableReplaced(VariableExpression oldVar, VariableExpression newVar)
+
+    static VariableReplacedListener NULL = new VariableReplacedListener() {
+        @Override
+        void variableReplaced(VariableExpression oldVar, VariableExpression 
newVar) {
+            //do nothing
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/groovy/blob/10110145/src/main/groovy/org/codehaus/groovy/transform/tailrec/VariableExpressionReplacer.groovy
----------------------------------------------------------------------
diff --git 
a/src/main/groovy/org/codehaus/groovy/transform/tailrec/VariableExpressionReplacer.groovy
 
b/src/main/groovy/org/codehaus/groovy/transform/tailrec/VariableExpressionReplacer.groovy
new file mode 100644
index 0000000..1f14490
--- /dev/null
+++ 
b/src/main/groovy/org/codehaus/groovy/transform/tailrec/VariableExpressionReplacer.groovy
@@ -0,0 +1,171 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.codehaus.groovy.transform.tailrec
+
+import groovy.transform.CompileStatic
+import org.codehaus.groovy.ast.ASTNode
+import org.codehaus.groovy.ast.CodeVisitorSupport
+import org.codehaus.groovy.ast.expr.BinaryExpression
+import org.codehaus.groovy.ast.expr.BooleanExpression
+import org.codehaus.groovy.ast.expr.Expression
+import org.codehaus.groovy.ast.expr.ExpressionTransformer
+import org.codehaus.groovy.ast.expr.VariableExpression
+import org.codehaus.groovy.ast.stmt.AssertStatement
+import org.codehaus.groovy.ast.stmt.CaseStatement
+import org.codehaus.groovy.ast.stmt.DoWhileStatement
+import org.codehaus.groovy.ast.stmt.ExpressionStatement
+import org.codehaus.groovy.ast.stmt.ForStatement
+import org.codehaus.groovy.ast.stmt.IfStatement
+import org.codehaus.groovy.ast.stmt.ReturnStatement
+import org.codehaus.groovy.ast.stmt.SwitchStatement
+import org.codehaus.groovy.ast.stmt.SynchronizedStatement
+import org.codehaus.groovy.ast.stmt.ThrowStatement
+import org.codehaus.groovy.ast.stmt.WhileStatement
+
+import java.lang.reflect.Method
+
+/**
+ * Tool for replacing VariableExpression instances in an AST by other 
VariableExpression instances.
+ * Regardless of a real change taking place in nested expressions, all 
considered expression (trees) will be replaced.
+ * This could be optimized to accelerate compilation.
+ *
+ * Within @TailRecursive it is used
+ * - to swap the access of method args with the access to iteration variables
+ * - to swap the access of iteration variables with the access of temp vars
+ *
+ * @author Johannes Link
+ */
+@CompileStatic
+class VariableExpressionReplacer extends CodeVisitorSupport {
+
+    Closure<Boolean> when = { VariableExpression node -> false }
+    Closure<VariableExpression> replaceWith = { VariableExpression 
variableExpression -> variableExpression }
+
+    private ExpressionTransformer transformer
+
+    synchronized void replaceIn(ASTNode root) {
+        transformer = new VariableExpressionTransformer(when: when, 
replaceWith: replaceWith)
+        root.visit(this)
+    }
+
+    public void visitReturnStatement(ReturnStatement statement) {
+        replaceExpressionPropertyWhenNecessary(statement)
+        super.visitReturnStatement(statement);
+    }
+
+    public void visitIfElse(IfStatement ifElse) {
+        replaceExpressionPropertyWhenNecessary(ifElse, 'booleanExpression', 
BooleanExpression)
+        super.visitIfElse(ifElse);
+    }
+
+    public void visitForLoop(ForStatement forLoop) {
+        replaceExpressionPropertyWhenNecessary(forLoop, 'collectionExpression')
+        super.visitForLoop(forLoop);
+    }
+
+    /**
+     * It's the only Expression type in which replacing is considered.
+     * That's an abuse of the class, but I couldn't think of a better way.
+     */
+    public void visitBinaryExpression(BinaryExpression expression) {
+        //A hack: Only replace right expression b/c 
ReturnStatementToIterationConverter needs it that way :-/
+        replaceExpressionPropertyWhenNecessary(expression, 'rightExpression')
+        expression.getRightExpression().visit(this);
+        super.visitBinaryExpression(expression)
+    }
+
+    public void visitWhileLoop(WhileStatement loop) {
+        replaceExpressionPropertyWhenNecessary(loop, 'booleanExpression', 
BooleanExpression)
+        super.visitWhileLoop(loop);
+    }
+
+    public void visitDoWhileLoop(DoWhileStatement loop) {
+        replaceExpressionPropertyWhenNecessary(loop, 'booleanExpression', 
BooleanExpression)
+        super.visitDoWhileLoop(loop);
+    }
+
+    public void visitSwitch(SwitchStatement statement) {
+        replaceExpressionPropertyWhenNecessary(statement)
+        super.visitSwitch(statement)
+    }
+
+    public void visitCaseStatement(CaseStatement statement) {
+        replaceExpressionPropertyWhenNecessary(statement)
+        super.visitCaseStatement(statement)
+    }
+
+    public void visitExpressionStatement(ExpressionStatement statement) {
+        replaceExpressionPropertyWhenNecessary(statement)
+        super.visitExpressionStatement(statement);
+    }
+
+    public void visitThrowStatement(ThrowStatement statement) {
+        replaceExpressionPropertyWhenNecessary(statement)
+        super.visitThrowStatement(statement)
+    }
+
+    public void visitAssertStatement(AssertStatement statement) {
+        replaceExpressionPropertyWhenNecessary(statement, 'booleanExpression', 
BooleanExpression)
+        replaceExpressionPropertyWhenNecessary(statement, 'messageExpression')
+        super.visitAssertStatement(statement)
+    }
+
+    public void visitSynchronizedStatement(SynchronizedStatement statement) {
+        replaceExpressionPropertyWhenNecessary(statement)
+        super.visitSynchronizedStatement(statement)
+    }
+
+    private void replaceExpressionPropertyWhenNecessary(ASTNode node, String 
propName = "expression", Class propClass = Expression) {
+        Expression expr = getExpression(node, propName)
+
+        if (expr instanceof VariableExpression) {
+            if (when(expr)) {
+                VariableExpression newExpr = replaceWith(expr)
+                replaceExpression(node, propName, propClass, expr, newExpr)
+            }
+        } else {
+            Expression newExpr = expr.transformExpression(transformer)
+            replaceExpression(node, propName, propClass, expr, newExpr)
+        }
+    }
+
+    private void replaceExpression(ASTNode node, String propName, Class 
propClass, Expression oldExpr, Expression newExpr) {
+        //Use reflection to enable CompileStatic
+        String setterName = 'set' + capitalizeFirst(propName)
+        Method setExpressionMethod = node.class.getMethod(setterName, 
[propClass].toArray(new Class[1]))
+        newExpr.setSourcePosition(oldExpr);
+        newExpr.copyNodeMetaData(oldExpr);
+        setExpressionMethod.invoke(node, [newExpr].toArray())
+    }
+
+    private Expression getExpression(ASTNode node, String propName) {
+        //Use reflection to enable CompileStatic
+        String getterName = 'get' + capitalizeFirst(propName)
+        Method getExpressionMethod = node.class.getMethod(getterName, new 
Class[0])
+        getExpressionMethod.invoke(node, new Object[0]) as Expression
+    }
+
+    private String capitalizeFirst(String propName) {
+        propName[0].toUpperCase() + propName[1..-1]
+    }
+
+
+}
+
+

http://git-wip-us.apache.org/repos/asf/groovy/blob/10110145/src/main/groovy/org/codehaus/groovy/transform/tailrec/VariableExpressionTransformer.groovy
----------------------------------------------------------------------
diff --git 
a/src/main/groovy/org/codehaus/groovy/transform/tailrec/VariableExpressionTransformer.groovy
 
b/src/main/groovy/org/codehaus/groovy/transform/tailrec/VariableExpressionTransformer.groovy
new file mode 100644
index 0000000..106a2f1
--- /dev/null
+++ 
b/src/main/groovy/org/codehaus/groovy/transform/tailrec/VariableExpressionTransformer.groovy
@@ -0,0 +1,47 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.codehaus.groovy.transform.tailrec
+
+import groovy.transform.CompileStatic
+import org.codehaus.groovy.ast.expr.Expression
+import org.codehaus.groovy.ast.expr.ExpressionTransformer
+import org.codehaus.groovy.ast.expr.VariableExpression
+
+/**
+ * An expression transformer used in the process of replacing the access to 
variables
+ *
+ * @author Johannes Link
+ */
+@CompileStatic
+class VariableExpressionTransformer implements ExpressionTransformer {
+
+    Closure<Boolean> when
+    Closure<VariableExpression> replaceWith
+
+    @Override
+    Expression transform(Expression expr) {
+        if ((expr instanceof VariableExpression) && when(expr)) {
+            VariableExpression newExpr = replaceWith(expr)
+            newExpr.setSourcePosition(expr);
+            newExpr.copyNodeMetaData(expr);
+            return newExpr
+        }
+        return expr.transformExpression(this)
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/10110145/src/main/groovy/org/codehaus/groovy/util/StringUtil.groovy
----------------------------------------------------------------------
diff --git a/src/main/groovy/org/codehaus/groovy/util/StringUtil.groovy 
b/src/main/groovy/org/codehaus/groovy/util/StringUtil.groovy
new file mode 100644
index 0000000..339d92c
--- /dev/null
+++ b/src/main/groovy/org/codehaus/groovy/util/StringUtil.groovy
@@ -0,0 +1,57 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.codehaus.groovy.util
+
+import groovy.transform.CompileStatic
+
+/**
+ * String utility functions.
+ */
+@CompileStatic
+class StringUtil {
+    /**
+     * Provides Groovy with functionality similar to the unix tr command
+     * which translates a string replacing characters from a source set
+     * with characters from a replacement set.
+     *
+     * @since 1.7.3
+     */
+    static String tr(String text, String source, String replacement) {
+        if (!text || !source) { return text }
+        source = expandHyphen(source)
+        replacement = expandHyphen(replacement)
+
+        // padding replacement with a last character, if necessary
+        replacement = replacement.padRight(source.size(), 
replacement[replacement.size() - 1])
+
+        return text.collect { String original ->
+            if (source.contains(original)) {
+                replacement[source.lastIndexOf(original)]
+            } else {
+                original
+            }
+        }.join('')
+    }
+
+    // no expansion for hyphen at start or end of Strings
+    private static String expandHyphen(String text) {
+        if (!text.contains('-')) { return text }
+        return text.replaceAll(/(.)-(.)/, { all, begin, end -> 
(begin..end).join('') })
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/10110145/src/main/groovy/security/GroovyCodeSourcePermission.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/security/GroovyCodeSourcePermission.java 
b/src/main/groovy/security/GroovyCodeSourcePermission.java
deleted file mode 100644
index e723e0b..0000000
--- a/src/main/groovy/security/GroovyCodeSourcePermission.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- */
-package groovy.security;
-
-import java.security.BasicPermission;
-
-/**
- * Permission required to explicitly specify a codebase for a groovy script 
whose
- * codebase cannot be determined.  Typically this permission is only
- * required by clients that want to associate a code source with a script which
- * is a String or an InputStream.
- *
- * @author Steve Goetze
- */
-public final class GroovyCodeSourcePermission extends BasicPermission {
-
-    public GroovyCodeSourcePermission(String name) {
-        super(name);
-    }
-
-    public GroovyCodeSourcePermission(String name, String actions) {
-        super(name, actions);
-    }
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/10110145/src/main/groovy/security/package.html
----------------------------------------------------------------------
diff --git a/src/main/groovy/security/package.html 
b/src/main/groovy/security/package.html
deleted file mode 100644
index cb094ff..0000000
--- a/src/main/groovy/security/package.html
+++ /dev/null
@@ -1,30 +0,0 @@
-<!--
-
-     Licensed to the Apache Software Foundation (ASF) under one
-     or more contributor license agreements.  See the NOTICE file
-     distributed with this work for additional information
-     regarding copyright ownership.  The ASF licenses this file
-     to you under the Apache License, Version 2.0 (the
-     "License"); you may not use this file except in compliance
-     with the License.  You may obtain a copy of the License at
-
-       http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing,
-     software distributed under the License is distributed on an
-     "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-     KIND, either express or implied.  See the License for the
-     specific language governing permissions and limitations
-     under the License.
-
--->
-<html>
-  <head>
-    <title>package groovy.security.*</title>
-  </head>
-  <body>
-    <p>
-      Security-related classes
-    </p>
-  </body>
-</html>

http://git-wip-us.apache.org/repos/asf/groovy/blob/10110145/src/main/groovy/time/BaseDuration.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/time/BaseDuration.java 
b/src/main/groovy/time/BaseDuration.java
deleted file mode 100644
index e2cc023..0000000
--- a/src/main/groovy/time/BaseDuration.java
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- */
-package groovy.time;
-
-import org.codehaus.groovy.runtime.DefaultGroovyMethods;
-import org.codehaus.groovy.runtime.StringGroovyMethods;
-
-import java.util.ArrayList;
-import java.util.Calendar;
-import java.util.Date;
-import java.util.List;
-
-/**
- * Base class for date and time durations.
- *
- * @author John Wilson [email protected]
- * @see Duration
- */
-public abstract class BaseDuration implements Comparable<BaseDuration> {
-    protected final int years;
-    protected final int months;
-    protected final int days;
-    protected final int hours;
-    protected final int minutes;
-    protected final int seconds;
-    protected final int millis;
-
-    protected BaseDuration(final int years, final int months, final int days, 
final int hours, final int minutes, final int seconds, final int millis) {
-        this.years = years;
-        this.months = months;
-        this.days = days;
-        this.hours = hours;
-        this.minutes = minutes;
-        this.seconds = seconds;
-        this.millis = millis;
-    }
-
-    protected BaseDuration(final int days, final int hours, final int minutes, 
final int seconds, final int millis) {
-        this(0, 0, days, hours, minutes, seconds, millis);
-    }
-
-    public int getYears() {
-        return this.years;
-    }
-
-    public int getMonths() {
-        return this.months;
-    }
-
-    public int getDays() {
-        return this.days;
-    }
-
-    public int getHours() {
-        return this.hours;
-    }
-
-    public int getMinutes() {
-        return this.minutes;
-    }
-
-    public int getSeconds() {
-        return this.seconds;
-    }
-
-    public int getMillis() {
-        return this.millis;
-    }
-
-    public Date plus(final Date date) {
-        final Calendar cal = Calendar.getInstance();
-
-        cal.setTime(date);
-        cal.add(Calendar.YEAR, this.years);
-        cal.add(Calendar.MONTH, this.months);
-        cal.add(Calendar.DAY_OF_YEAR, this.days);
-        cal.add(Calendar.HOUR_OF_DAY, this.hours);
-        cal.add(Calendar.MINUTE, this.minutes);
-        cal.add(Calendar.SECOND, this.seconds);
-        cal.add(Calendar.MILLISECOND, this.millis);
-
-        return cal.getTime();
-    }
-
-    public String toString() {
-        List buffer = new ArrayList();
-
-        if (this.years != 0) buffer.add(this.years + " years");
-        if (this.months != 0) buffer.add(this.months + " months");
-        if (this.days != 0) buffer.add(this.days + " days");
-        if (this.hours != 0) buffer.add(this.hours + " hours");
-        if (this.minutes != 0) buffer.add(this.minutes + " minutes");
-
-        if (this.seconds != 0 || this.millis != 0) {
-            int norm_millis = this.millis % 1000;
-            int norm_seconds = this.seconds + 
DefaultGroovyMethods.intdiv(this.millis - norm_millis, 1000).intValue();
-            CharSequence millisToPad = "" + Math.abs(norm_millis);
-            buffer.add((norm_seconds == 0 ? (norm_millis < 0 ? "-0" : "0") : 
norm_seconds) + "." + StringGroovyMethods.padLeft(millisToPad, 3, "0") + " 
seconds");
-        }
-
-        if (!buffer.isEmpty()) {
-            return DefaultGroovyMethods.join(buffer.iterator(), ", ");
-        } else {
-            return "0";
-        }
-    }
-
-    public abstract long toMilliseconds();
-
-    public abstract Date getAgo();
-
-    public abstract From getFrom();
-
-    public int compareTo(BaseDuration otherDuration) {
-        return Long.signum(toMilliseconds() - otherDuration.toMilliseconds());
-    }
-
-    public abstract static class From {
-        public abstract Date getNow();
-
-        public Date getToday() {
-            return getNow();
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/10110145/src/main/groovy/time/DatumDependentDuration.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/time/DatumDependentDuration.java 
b/src/main/groovy/time/DatumDependentDuration.java
deleted file mode 100644
index c73d9aa..0000000
--- a/src/main/groovy/time/DatumDependentDuration.java
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- */
-package groovy.time;
-
-import java.util.Calendar;
-import java.util.Date;
-
-/**
- * DatumDependentDuration represents durations whose length in milliseconds 
- * cannot be determined without knowing the datum point.
- * <p>
- * I don't know how many days in a year unless I know if it's a leap year or 
not.
- * <p>
- * I don't know how many days in a month unless I know the name of the month 
- * (and if it's a leap year if the month is February)
- *
- * @author John Wilson [email protected]
- */
-public class DatumDependentDuration extends BaseDuration {
-    public DatumDependentDuration(final int years, final int months, final int 
days, final int hours, final int minutes, final int seconds, final int millis) {
-        super(years, months, days, hours, minutes, seconds, millis);
-    }
-
-    public int getMonths() {
-        return this.months;
-    }
-
-    public int getYears() {
-        return this.years;
-    }
-
-    public DatumDependentDuration plus(final DatumDependentDuration rhs) {
-        return new DatumDependentDuration(this.getYears() + rhs.getYears(), 
this.getMonths() + rhs.getMonths(),
-                this.getDays() + rhs.getDays(), this.getHours() + 
rhs.getHours(),
-                this.getMinutes() + rhs.getMinutes(), this.getSeconds() + 
rhs.getSeconds(),
-                this.getMillis() + rhs.getMillis());
-    }
-
-    public DatumDependentDuration plus(final TimeDatumDependentDuration rhs) {
-        return rhs.plus(this);
-    }
-
-    public DatumDependentDuration plus(final Duration rhs) {
-        return new DatumDependentDuration(this.getYears(), this.getMonths(),
-                this.getDays() + rhs.getDays(), this.getHours() + 
rhs.getHours(),
-                this.getMinutes() + rhs.getMinutes(), this.getSeconds() + 
rhs.getSeconds(),
-                this.getMillis() + rhs.getMillis());
-
-    }
-
-    public DatumDependentDuration plus(final TimeDuration rhs) {
-        return rhs.plus(this);
-
-    }
-
-    public DatumDependentDuration minus(final DatumDependentDuration rhs) {
-        return new DatumDependentDuration(this.getYears() - rhs.getYears(), 
this.getMonths() - rhs.getMonths(),
-                this.getDays() - rhs.getDays(), this.getHours() - 
rhs.getHours(),
-                this.getMinutes() - rhs.getMinutes(), this.getSeconds() - 
rhs.getSeconds(),
-                this.getMillis() - rhs.getMillis());
-
-    }
-
-    public DatumDependentDuration minus(final Duration rhs) {
-        return new DatumDependentDuration(this.getYears(), this.getMonths(),
-                this.getDays() - rhs.getDays(), this.getHours() - 
rhs.getHours(),
-                this.getMinutes() - rhs.getMinutes(), this.getSeconds() - 
rhs.getSeconds(),
-                this.getMillis() - rhs.getMillis());
-
-    }
-
-    /**
-     * @see groovy.time.BaseDuration#toMilliseconds()
-     *
-     * Change the duration into milliseconds, relative to 'now.'  Therefore
-     * things like timezone and time of year will affect how this conversion 
-     * occurs.
-     */
-    public long toMilliseconds() {
-        final Date now = new Date();
-        return TimeCategory.minus(plus(now), now).toMilliseconds();
-    }
-
-    public Date getAgo() {
-        final Calendar cal = Calendar.getInstance();
-
-        cal.add(Calendar.YEAR, -this.getYears());
-        cal.add(Calendar.MONTH, -this.getMonths());
-        cal.add(Calendar.DAY_OF_YEAR, -this.getDays());
-        cal.add(Calendar.HOUR_OF_DAY, -this.getHours());
-        cal.add(Calendar.MINUTE, -this.getMinutes());
-        cal.add(Calendar.SECOND, -this.getSeconds());
-        cal.add(Calendar.MILLISECOND, -this.getMillis());
-
-        cal.set(Calendar.HOUR_OF_DAY, 0);
-        cal.set(Calendar.MINUTE, 0);
-        cal.set(Calendar.SECOND, 0);
-        cal.set(Calendar.MILLISECOND, 0);
-
-        return new Date(cal.getTimeInMillis());
-    }
-
-    public From getFrom() {
-        return new From() {
-            public Date getNow() {
-                final Calendar cal = Calendar.getInstance();
-
-                cal.add(Calendar.YEAR, DatumDependentDuration.this.getYears());
-                cal.add(Calendar.MONTH, 
DatumDependentDuration.this.getMonths());
-                cal.add(Calendar.DAY_OF_YEAR, 
DatumDependentDuration.this.getDays());
-                cal.add(Calendar.HOUR_OF_DAY, 
DatumDependentDuration.this.getHours());
-                cal.add(Calendar.MINUTE, 
DatumDependentDuration.this.getMinutes());
-                cal.add(Calendar.SECOND, 
DatumDependentDuration.this.getSeconds());
-                cal.add(Calendar.MILLISECOND, 
DatumDependentDuration.this.getMillis());
-
-                cal.set(Calendar.HOUR_OF_DAY, 0);
-                cal.set(Calendar.MINUTE, 0);
-                cal.set(Calendar.SECOND, 0);
-                cal.set(Calendar.MILLISECOND, 0);
-
-                return new Date(cal.getTimeInMillis());
-            }
-        };
-    }
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/10110145/src/main/groovy/time/Duration.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/time/Duration.java 
b/src/main/groovy/time/Duration.java
deleted file mode 100644
index e187957..0000000
--- a/src/main/groovy/time/Duration.java
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- */
-package groovy.time;
-
-import java.util.Calendar;
-import java.util.Date;
-
-/**
- * Duration represents time periods which have values independent of the 
context.
- * So, whilst we can't say how long a month is without knowing the year and 
the name of the month,
- * we know how long a day is independent of the date.
- * <p>
- * This is not 100% true for days.
- * Days can actually be 23, 24 or 25 hours long (due to daylight saving 
adjustments.)
- * <p>
- * If you ask Duration to convert itself to milliseconds then it will work on 
the basis of 24 hours
- * in a day. If you add or subtract it from a date it will take daylight 
saving into account.
- *
- * @author John Wilson [email protected]
- */
-public class Duration extends BaseDuration {
-    public Duration(final int days, final int hours, final int minutes, final 
int seconds, final int millis) {
-        super(days, hours, minutes, seconds, millis);
-    }
-    
-    public Duration plus(final Duration rhs) {
-        return new Duration(this.getDays() + rhs.getDays(), this.getHours() + 
rhs.getHours(),
-                            this.getMinutes() + rhs.getMinutes(), 
this.getSeconds() + rhs.getSeconds(),
-                            this.getMillis() + rhs.getMillis());
-    }
-
-    public Duration plus(final TimeDuration rhs) {
-        return rhs.plus(this);
-    }
-    
-    public DatumDependentDuration plus(final DatumDependentDuration rhs) {
-        return rhs.plus(this);
-    }
-    
-    public Duration minus(final Duration rhs) {
-        return new Duration(this.getDays() - rhs.getDays(), this.getHours() - 
rhs.getHours(),
-                            this.getMinutes() - rhs.getMinutes(), 
this.getSeconds() - rhs.getSeconds(),
-                            this.getMillis() - rhs.getMillis());
-    }
-    
-    public TimeDuration minus(final TimeDuration rhs) {
-        return new TimeDuration(this.getDays() - rhs.getDays(), 
this.getHours() - rhs.getHours(),
-                                this.getMinutes() - rhs.getMinutes(), 
this.getSeconds() - rhs.getSeconds(),
-                                this.getMillis() - rhs.getMillis());
-    }
-    
-    public DatumDependentDuration minus(final DatumDependentDuration rhs) {
-        return new DatumDependentDuration(-rhs.getYears(), -rhs.getMonths(),
-                                          this.getDays() - rhs.getDays(), 
this.getHours() - rhs.getHours(),
-                                          this.getMinutes() - 
rhs.getMinutes(), this.getSeconds() - rhs.getSeconds(),
-                                          this.getMillis() - rhs.getMillis());
-    }
-    
-    public TimeDatumDependentDuration minus(final TimeDatumDependentDuration 
rhs) {
-        return new TimeDatumDependentDuration(-rhs.getYears(), 
-rhs.getMonths(),
-                                              this.getDays() - rhs.getDays(), 
this.getHours() - rhs.getHours(),
-                                              this.getMinutes() - 
rhs.getMinutes(), this.getSeconds() - rhs.getSeconds(),
-                                              this.getMillis() - 
rhs.getMillis());
-    }
-    
-    public long toMilliseconds() {
-        return ((((((long)(this.getDays() * 24 ) + this.getHours()) * 60 + 
this.getMinutes()) * 60) + this.getSeconds()) * 1000) + this.getMillis();
-    }
-    
-    public Date getAgo() {
-    final Calendar cal = Calendar.getInstance();
-
-        cal.add(Calendar.DAY_OF_YEAR, -this.getDays());
-        cal.add(Calendar.HOUR_OF_DAY, -this.getHours());
-        cal.add(Calendar.MINUTE, -this.getMinutes());
-        cal.add(Calendar.SECOND, -this.getSeconds());
-        cal.add(Calendar.MILLISECOND, -this.getMillis());
-
-        cal.set(Calendar.HOUR_OF_DAY, 0);
-        cal.set(Calendar.MINUTE, 0);
-        cal.set(Calendar.SECOND, 0);
-        cal.set(Calendar.MILLISECOND, 0);
-        
-        return new Date(cal.getTimeInMillis());
-    }
-     
-    public From getFrom() {
-        return new From() {
-            public Date getNow() {
-            final Calendar cal = Calendar.getInstance();
-
-                cal.add(Calendar.DAY_OF_YEAR, Duration.this.getDays());
-
-                cal.set(Calendar.HOUR_OF_DAY, 0);
-                cal.set(Calendar.MINUTE, 0);
-                cal.set(Calendar.SECOND, 0);
-                cal.set(Calendar.MILLISECOND, 0);
-
-                return new Date(cal.getTimeInMillis());
-            }
-        };
-    }
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/10110145/src/main/groovy/time/TimeCategory.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/time/TimeCategory.java 
b/src/main/groovy/time/TimeCategory.java
deleted file mode 100644
index dbc08cd..0000000
--- a/src/main/groovy/time/TimeCategory.java
+++ /dev/null
@@ -1,203 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- */
-package groovy.time;
-
-import java.util.Calendar;
-import java.util.Date;
-import java.util.TimeZone;
-
-/**
- * Apply a number of methods to allow convenient Date/Time manipulation,such 
as:
- * <pre class="groovyTestCase">
- * use (groovy.time.TimeCategory) {
- *     // application on numbers:
- *     println 1.minute.from.now
- *     println 10.hours.ago
- *
- *     // application on dates
- *     def someDate = new Date()
- *     println someDate - 3.months
- * }
- * </pre>
- *
- * @see BaseDuration
- */
-public class TimeCategory {
-    /*
-     * Methods to allow Date Duration arithmetic
-     */
-
-    public static Date plus(final Date date, final BaseDuration duration) {
-        return duration.plus(date);
-    }
-
-    public static Date minus(final Date date, final BaseDuration duration) {
-        final Calendar cal = Calendar.getInstance();
-
-        cal.setTime(date);
-        cal.add(Calendar.YEAR, -duration.getYears());
-        cal.add(Calendar.MONTH, -duration.getMonths());
-        cal.add(Calendar.DAY_OF_YEAR, -duration.getDays());
-        cal.add(Calendar.HOUR_OF_DAY, -duration.getHours());
-        cal.add(Calendar.MINUTE, -duration.getMinutes());
-        cal.add(Calendar.SECOND, -duration.getSeconds());
-        cal.add(Calendar.MILLISECOND, -duration.getMillis());
-
-        return cal.getTime();
-    }
-
-    /**
-     * Retrieves the default TimeZone for a date by using the default Locale
-     * settings. Recommended that you use {@code TimeZone.getDefault()} 
instead.
-     *
-     * @param self a Date
-     * @return the TimeZone
-     */
-    @Deprecated
-    public static TimeZone getTimeZone(Date self) {
-        Calendar calendar = Calendar.getInstance();
-        calendar.setTime(self);
-        return calendar.getTimeZone();
-    }
-
-    /**
-     * Get the DST offset (if any) for the default locale and the given date.
-     *
-     * @param self a Date
-     * @return the DST offset as a Duration.
-     */
-    public static Duration getDaylightSavingsOffset(Date self) {
-        TimeZone timeZone = getTimeZone(self);
-        int millis = (timeZone.useDaylightTime() && 
timeZone.inDaylightTime(self))
-                ? timeZone.getDSTSavings() : 0;
-        return new TimeDuration(0, 0, 0, millis);
-    }
-
-    public static Duration getDaylightSavingsOffset(BaseDuration self) {
-        return getDaylightSavingsOffset(new Date(self.toMilliseconds() + 1));
-    }
-
-    /**
-     * Return a Duration representing the DST difference (if any) between two
-     * dates.  i.e. if one date is before the DST changeover, and the other
-     * date is after, the resulting duration will represent the DST offset.
-     *
-     * @param self  a Date
-     * @param other another Date
-     * @return a Duration
-     */
-    public static Duration getRelativeDaylightSavingsOffset(Date self, Date 
other) {
-        Duration d1 = getDaylightSavingsOffset(self);
-        Duration d2 = getDaylightSavingsOffset(other);
-        return new TimeDuration(0, 0, 0, (int) (d2.toMilliseconds() - 
d1.toMilliseconds()));
-    }
-
-    /**
-     * Subtract one date from the other.
-     *
-     * @param lhs a Date
-     * @param rhs another Date
-     * @return a Duration
-     */
-    public static TimeDuration minus(final Date lhs, final Date rhs) {
-        long milliseconds = lhs.getTime() - rhs.getTime();
-        long days = milliseconds / (24 * 60 * 60 * 1000);
-        milliseconds -= days * 24 * 60 * 60 * 1000;
-        int hours = (int) (milliseconds / (60 * 60 * 1000));
-        milliseconds -= hours * 60 * 60 * 1000;
-        int minutes = (int) (milliseconds / (60 * 1000));
-        milliseconds -= minutes * 60 * 1000;
-        int seconds = (int) (milliseconds / 1000);
-        milliseconds -= seconds * 1000;
-
-        return new TimeDuration((int) days, hours, minutes, seconds, (int) 
milliseconds);
-    }
-
-    /*
-    * Methods on Integer to implement 1.month, 4.years etc.
-    */
-
-    public static DatumDependentDuration getMonths(final Integer self) {
-        return new DatumDependentDuration(0, self, 0, 0, 0, 0, 0);
-    }
-
-    public static DatumDependentDuration getMonth(final Integer self) {
-        return getMonths(self);
-    }
-
-    public static DatumDependentDuration getYears(final Integer self) {
-        return new DatumDependentDuration(self, 0, 0, 0, 0, 0, 0);
-    }
-
-    public static DatumDependentDuration getYear(final Integer self) {
-        return getYears(self);
-    }
-
-    /*
-    * Methods on Integer to implement 1.week, 4.days etc.
-    */
-
-    public static Duration getWeeks(final Integer self) {
-        return new Duration(self * 7, 0, 0, 0, 0);
-    }
-
-    public static Duration getWeek(final Integer self) {
-        return getWeeks(self);
-    }
-
-    public static Duration getDays(final Integer self) {
-        return new Duration(self, 0, 0, 0, 0);
-    }
-
-    public static Duration getDay(final Integer self) {
-        return getDays(self);
-    }
-
-    public static TimeDuration getHours(final Integer self) {
-        return new TimeDuration(0, self, 0, 0, 0);
-    }
-
-    public static TimeDuration getHour(final Integer self) {
-        return getHours(self);
-    }
-
-    public static TimeDuration getMinutes(final Integer self) {
-        return new TimeDuration(0, 0, self, 0, 0);
-    }
-
-    public static TimeDuration getMinute(final Integer self) {
-        return getMinutes(self);
-    }
-
-    public static TimeDuration getSeconds(final Integer self) {
-        return new TimeDuration(0, 0, 0, self, 0);
-    }
-
-    public static TimeDuration getSecond(final Integer self) {
-        return getSeconds(self);
-    }
-
-    public static TimeDuration getMilliseconds(final Integer self) {
-        return new TimeDuration(0, 0, 0, 0, self);
-    }
-
-    public static TimeDuration getMillisecond(final Integer self) {
-        return getMilliseconds(self);
-    }
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/10110145/src/main/groovy/time/TimeDatumDependentDuration.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/time/TimeDatumDependentDuration.java 
b/src/main/groovy/time/TimeDatumDependentDuration.java
deleted file mode 100644
index eead45a..0000000
--- a/src/main/groovy/time/TimeDatumDependentDuration.java
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- */
-package groovy.time;
-
-import java.util.Calendar;
-import java.util.Date;
-
-/**
- * TimeDatumDuration represents a time period which results from an
- * arithmetic operation between a TimeDuration object and a DatumDuration 
object
- * 
- * @author John Wilson [email protected]
- */
-public class TimeDatumDependentDuration extends DatumDependentDuration {
-    public TimeDatumDependentDuration(int years, int months, int days, int 
hours, int minutes, int seconds, int millis) {
-        super(years, months, days, hours, minutes, seconds, millis);
-    }
-    
-    public DatumDependentDuration plus(final Duration rhs) {
-        return new TimeDatumDependentDuration(this.getYears(), 
this.getMonths(),
-                                              this.getDays() + rhs.getDays(), 
this.getHours() + rhs.getHours(),
-                                              this.getMinutes() + 
rhs.getMinutes(), this.getSeconds() + rhs.getSeconds(),
-                                              this.getMillis() + 
rhs.getMillis());
-    }
-    
-    public DatumDependentDuration plus(final DatumDependentDuration rhs) {
-        return new TimeDatumDependentDuration(this.getYears() + 
rhs.getYears(), this.getMonths() + rhs.getMonths(),
-                                              this.getDays() + rhs.getDays(), 
this.getHours() + rhs.getHours(),
-                                              this.getMinutes() + 
rhs.getMinutes(), this.getSeconds() + rhs.getSeconds(),
-                                              this.getMillis() + 
rhs.getMillis());
-    }
-    
-    public DatumDependentDuration minus(final Duration rhs) {
-        return new TimeDatumDependentDuration(this.getYears(), 
this.getMonths(),
-                                              this.getDays() - rhs.getDays(), 
this.getHours() - rhs.getHours(),
-                                              this.getMinutes() - 
rhs.getMinutes(), this.getSeconds() - rhs.getSeconds(),
-                                              this.getMillis() - 
rhs.getMillis());
-    }
-    
-    public DatumDependentDuration minus(final DatumDependentDuration rhs) {
-        return new TimeDatumDependentDuration(this.getYears() - 
rhs.getYears(), this.getMonths() - rhs.getMonths(),
-                                              this.getDays() - rhs.getDays(), 
this.getHours() - rhs.getHours(),
-                                              this.getMinutes() - 
rhs.getMinutes(), this.getSeconds() - rhs.getSeconds(),
-                                              this.getMillis() - 
rhs.getMillis());
-    }
-    
-    public From getFrom() {
-        return new From() {
-            public Date getNow() {
-            final Calendar cal = Calendar.getInstance();
-
-                cal.add(Calendar.YEAR, 
TimeDatumDependentDuration.this.getYears());
-                cal.add(Calendar.MONTH, 
TimeDatumDependentDuration.this.getMonths());
-                cal.add(Calendar.DAY_OF_YEAR, 
TimeDatumDependentDuration.this.getDays());
-                cal.add(Calendar.HOUR_OF_DAY, 
TimeDatumDependentDuration.this.getHours());
-                cal.add(Calendar.MINUTE, 
TimeDatumDependentDuration.this.getMinutes());
-                cal.add(Calendar.SECOND, 
TimeDatumDependentDuration.this.getSeconds());
-                cal.add(Calendar.MILLISECOND, 
TimeDatumDependentDuration.this.getMillis());
-                
-                return cal.getTime();
-            }
-        };
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/10110145/src/main/groovy/time/TimeDuration.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/time/TimeDuration.java 
b/src/main/groovy/time/TimeDuration.java
deleted file mode 100644
index 767b8e6..0000000
--- a/src/main/groovy/time/TimeDuration.java
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- */
-package groovy.time;
-
-import java.util.Calendar;
-import java.util.Date;
-
-/**
- * TimeDuration represents time periods expressed in units of hours, minutes,
- * seconds and milliseconds.
- * <p>
- * Whilst we can't say how long a month is without knowing the year and the 
name of the month,
- * we know how long a second is independent of the date.
- * <p>
- * This is not 100% true for minutes.
- * Minutes can be 59, 60 or 61 seconds long (due to leap seconds.)
- * <p>
- * If you ask Duration to convert itself to milliseconds then it will work on 
the basis of 60 seconds in a minute.
- * If you add or subtract it from a date it will take leap seconds into 
account.
- *
- * @author John Wilson [email protected]
- */
-
-public class TimeDuration extends Duration {
-    public TimeDuration(final int hours, final int minutes, final int seconds, 
final int millis) {
-        super(0, hours, minutes, seconds, millis);
-     }
-    
-    public TimeDuration(final int days, final int hours, final int minutes, 
final int seconds, final int millis) {
-        super(days, hours, minutes, seconds, millis);
-     }
-    
-    public Duration plus(final Duration rhs) {
-        return new TimeDuration(this.getDays() + rhs.getDays(), 
this.getHours() + rhs.getHours(),
-                                this.getMinutes() + rhs.getMinutes(), 
this.getSeconds() + rhs.getSeconds(),
-                                this.getMillis() + rhs.getMillis());
-    }
-    
-    public DatumDependentDuration plus(final DatumDependentDuration rhs) {
-        return new TimeDatumDependentDuration(rhs.getYears(), rhs.getMonths(),
-                                              this.getDays() + rhs.getDays(), 
this.getHours() + rhs.getHours(),
-                                              this.getMinutes() + 
rhs.getMinutes(), this.getSeconds() + rhs.getSeconds(),
-                                              this.getMillis() + 
rhs.getMillis());
-    }
-    
-    public Duration minus(final Duration rhs) {
-        return new TimeDuration(this.getDays() - rhs.getDays(), 
this.getHours() - rhs.getHours(),
-                                this.getMinutes() - rhs.getMinutes(), 
this.getSeconds() - rhs.getSeconds(),
-                                this.getMillis() - rhs.getMillis());
-    }
-    
-    public DatumDependentDuration minus(final DatumDependentDuration rhs) {
-        return new TimeDatumDependentDuration(-rhs.getYears(), 
-rhs.getMonths(),
-                                              this.getDays() - rhs.getDays(), 
this.getHours() - rhs.getHours(),
-                                              this.getMinutes() - 
rhs.getMinutes(), this.getSeconds() - rhs.getSeconds(),
-                                              this.getMillis() - 
rhs.getMillis());
-    }
-    
-    public Date getAgo() {
-        final Calendar cal = Calendar.getInstance();
-
-        cal.add(Calendar.DAY_OF_YEAR, -this.getDays());
-        cal.add(Calendar.HOUR_OF_DAY, -this.getHours());
-        cal.add(Calendar.MINUTE, -this.getMinutes());
-        cal.add(Calendar.SECOND, -this.getSeconds());
-        cal.add(Calendar.MILLISECOND, -this.getMillis());
-        
-        return cal.getTime();
-    }        
-
-    public From getFrom() {
-        return new From() {
-            public Date getNow() {
-                final Calendar cal = Calendar.getInstance();
-
-                cal.add(Calendar.DAY_OF_YEAR, TimeDuration.this.getDays());
-                cal.add(Calendar.HOUR_OF_DAY, TimeDuration.this.getHours());
-                cal.add(Calendar.MINUTE, TimeDuration.this.getMinutes());
-                cal.add(Calendar.SECOND, TimeDuration.this.getSeconds());
-                cal.add(Calendar.MILLISECOND, TimeDuration.this.getMillis());
-                
-                return cal.getTime();
-            }
-        };
-    }
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/10110145/src/main/groovy/time/package.html
----------------------------------------------------------------------
diff --git a/src/main/groovy/time/package.html 
b/src/main/groovy/time/package.html
deleted file mode 100644
index 94fb458..0000000
--- a/src/main/groovy/time/package.html
+++ /dev/null
@@ -1,47 +0,0 @@
-<!--
-
-     Licensed to the Apache Software Foundation (ASF) under one
-     or more contributor license agreements.  See the NOTICE file
-     distributed with this work for additional information
-     regarding copyright ownership.  The ASF licenses this file
-     to you under the Apache License, Version 2.0 (the
-     "License"); you may not use this file except in compliance
-     with the License.  You may obtain a copy of the License at
-
-       http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing,
-     software distributed under the License is distributed on an
-     "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-     KIND, either express or implied.  See the License for the
-     specific language governing permissions and limitations
-     under the License.
-
--->
-<html>
-  <head>
-    <title>package groovy.time.*</title>
-  </head>
-  <body>
-    <p>
-      Classes for easily manipulating Dates and times.  While 
-      <code>java.util.Date</code> has GDK methods for adding or subtracting 
days,
-      this is not so useful for different durations of time.  
-      {@link groovy.time.TimeCategory TimeCategory} creates a simple internal 
DSL
-      for manipulating dates and times in a clean and precise fashion.  
-    </p>
-    <h3>Examples</h3>
-    <pre>
-  use ( TimeCategory ) {
-       // application on numbers:
-       println 1.minute.from.now
-       println 10.days.ago
-  
-       // application on dates
-       def someDate = new Date()
-       println someDate - 3.months 
-  }</pre>
-     
-    @see groovy.time.TimeCategory
-  </body>
-</html>

http://git-wip-us.apache.org/repos/asf/groovy/blob/10110145/src/main/groovy/transform/ASTTest.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/transform/ASTTest.java 
b/src/main/groovy/transform/ASTTest.java
deleted file mode 100644
index 1cdb480..0000000
--- a/src/main/groovy/transform/ASTTest.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- */
-package groovy.transform;
-
-import org.codehaus.groovy.control.CompilePhase;
-import org.codehaus.groovy.transform.GroovyASTTransformationClass;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * This AST transformation aims at helping in debugging other AST 
transformations. It provides a basic
- * infrastructure for performing tests on AST nodes. You can place this 
annotation on any node which
- * accepts an annotation (types, methods, annotations, constructors, fields, 
local variables, packages
- * or parameters), then use a script which is run against this AST node at a 
specific phase. For example,
- * you could test the {@link Field} AST transformation this way:
- *
- * <pre class="groovyTestCase">
- * import groovy.transform.*
- *
- * {@code @ASTTest}(value = {
- *    def owner = node.declaringClass
- *    assert owner.fields.any { it.name == 'x' }
- *  })
- * {@code @Field int x}
- *
- * </pre>
- *
- * The closure code is executed after the specified phase has completed. If no 
phase is selected, then the
- * code is executed after the {@link 
org.codehaus.groovy.control.CompilePhase#SEMANTIC_ANALYSIS semantic analysis} 
phase.
- * The <code>node</code> variable refers to the AST node where the AST test 
annotation is put. In the previous example,
- * it means that <i>node</i> refers to the declaration node (int x).
- *
- * @author Cedric Champeau
- * @since 2.0.0
- *
- */
[email protected]
-@Retention(RetentionPolicy.RUNTIME)
-@Target({ElementType.TYPE, ElementType.METHOD, ElementType.ANNOTATION_TYPE, 
ElementType.CONSTRUCTOR, ElementType.FIELD,
-ElementType.LOCAL_VARIABLE, ElementType.PACKAGE, ElementType.PARAMETER})
-@GroovyASTTransformationClass("org.codehaus.groovy.transform.ASTTestTransformation")
-public @interface ASTTest {
-    /**
-     * The compile phase after which the test code should run.
-     */
-    CompilePhase phase() default CompilePhase.SEMANTIC_ANALYSIS;
-
-    /**
-     * A closure which is executed against the annotated node after the 
specified phase has completed.
-     */
-    Class value();
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/10110145/src/main/groovy/transform/AnnotationCollector.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/transform/AnnotationCollector.java 
b/src/main/groovy/transform/AnnotationCollector.java
deleted file mode 100644
index b9f2161..0000000
--- a/src/main/groovy/transform/AnnotationCollector.java
+++ /dev/null
@@ -1,199 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- */
-package groovy.transform;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * The AnnotationCollector can be used to define aliases for groups of 
- * annotations. The Alias needs to be a class or annotation annotated with 
- * AnnotationCollector, otherwise nothing is required. The alias will be 
- * replaced on the AST level and will never appear in later. Any members of 
the 
- * class or annotation will be ignored, but could be used by a custom 
processor.
- * Annotation arguments are mapped to the aliased annotations
- * if existing. Should the default processor not be able to map one of the
- * arguments and error will be given. Is this not wished or if you want a 
- * different mapping a custom processor has to be used. There are two ways of 
- * using the alias. The first way is by providing the annotations as 
list/array:
- * <pre class="groovyTestCase">
- *          import groovy.transform.*
- *          &#64;AnnotationCollector([ToString, EqualsAndHashCode, Immutable])
- *          &#64;interface Alias {}
-
- *          &#64;Alias(excludes=["a"])
- *          class Foo {
- *              Integer a, b
- *          }
- *          assert Foo.class.annotations.size()==3 
- *          assert new Foo(1,2).toString() == "Foo(2)"
- * </pre>
- * In the example above we have Alias as the alias annotation and an argument
- * excludes which will be mapped to ToString and EqualsAndHashCode. Immutable 
- * doesn't have excludes, thus nothing will be done there.<br>
- * The other way is to add annotations to the alias:
- * <pre class="groovyTestCase">
- * import groovy.transform.*
- * &#64;ToString(excludes=["a"])
- * &#64;EqualsAndHashCode
- * &#64;Immutable
- * &#64;AnnotationCollector
- * &#64;interface Alias {}
- *
- * &#64;Alias
- * class Foo {
- *     Integer a, b
- * }
- * assert Foo.class.annotations.size()==3
- * assert new Foo(1,2).toString() == "Foo(2)"
- * </pre>
- * In the example above we have again Alias as the alias annotation, but
- * this time the argument is part of the alias. Instead of mapping excludes to
- * ToString as well as EqualsAndHashCode, only ToString will have the excludes.
- * Again the alias can have an argument excludes, which would overwrite the 
- * excludes given in from the definition and be mapped to ToString as well as
- * 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 class="groovyTestCase">
- * //--------------------------------------------------------------------------
- * import groovy.transform.*
- * &#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 class="groovyTestCase">
- * //--------------------------------------------------------------------------
- * // 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 class="groovyTestCase">
- * //--------------------------------------------------------------------------
- * // Use AnnotationCollector as last annotation to group the
- * // previous annotations.
- * import groovy.transform.*
- * &#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:[email protected]";>Jochen "blackdrag" Theodorou</a>
- * @see org.codehaus.groovy.transform.AnnotationCollectorTransform
- */
[email protected]
-@Retention(RetentionPolicy.RUNTIME)
-@Target({ElementType.ANNOTATION_TYPE, ElementType.TYPE})
-public @interface AnnotationCollector {
-    /**
-     * Processor used for computing custom logic or the list of annotations, 
or 
-     * both. The default is 
org.codehaus.groovy.transform.AnnotationCollectorTransform.
-     * Custom processors need to extend that class. 
-     */
-    String processor() default 
"org.codehaus.groovy.transform.AnnotationCollectorTransform";
-
-    /**
-     * When the collector annotation is replaced, whether to check for 
duplicates between
-     * the replacement annotations and existing explicit annotations.
-     * If you use a custom processor, it is up to that processor whether it 
honors or ignores
-     * this parameter. The default processor honors the parameter.
-     */
-    AnnotationCollectorMode mode() default AnnotationCollectorMode.DUPLICATE;
-
-    /**
-     * List of aliased annotations.
-     */
-    Class[] value() default {};
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/10110145/src/main/groovy/transform/AnnotationCollectorMode.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/transform/AnnotationCollectorMode.java 
b/src/main/groovy/transform/AnnotationCollectorMode.java
deleted file mode 100644
index 308d0c0..0000000
--- a/src/main/groovy/transform/AnnotationCollectorMode.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-
-package groovy.transform;
-
-public enum AnnotationCollectorMode {
-    // TODO should we support @Repeatable from Java 8?
-    /**
-     * Annotations from the annotation collection will always be inserted. 
After all transforms have been run, it will
-     * be an error if multiple annotations (excluding those with SOURCE 
retention) exist.
-     */
-    DUPLICATE,
-
-    /**
-     * Annotations from the collector will be added and any existing 
annotations with the same name will be removed.
-     */
-    PREFER_COLLECTOR,
-
-    /**
-     * Annotations from the collector will be ignored if any existing 
annotations with the same name are found.
-     */
-    PREFER_EXPLICIT,
-
-    /**
-     * Annotations from the collector will be added and any existing 
annotations with the same name will be removed but any new parameters found 
within existing annotations will be merged into the added annotation.
-     */
-    PREFER_COLLECTOR_MERGED,
-
-    /**
-     * Annotations from the collector will be ignored if any existing 
annotations with the same name are found but any new parameters on the 
collector annotation will be added to existing annotations.
-     */
-    PREFER_EXPLICIT_MERGED
-}

Reply via email to