You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by su...@apache.org on 2017/12/20 00:56:30 UTC

[33/49] groovy git commit: Move source files to proper packages

http://git-wip-us.apache.org/repos/asf/groovy/blob/10110145/src/main/groovy/groovy/lang/SpreadListEvaluatingException.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/lang/SpreadListEvaluatingException.java b/src/main/groovy/groovy/lang/SpreadListEvaluatingException.java
new file mode 100644
index 0000000..b6de965
--- /dev/null
+++ b/src/main/groovy/groovy/lang/SpreadListEvaluatingException.java
@@ -0,0 +1,25 @@
+/*
+ *  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.lang;
+
+public class SpreadListEvaluatingException extends GroovyRuntimeException {
+    public SpreadListEvaluatingException(String message) {
+        super(message);
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/10110145/src/main/groovy/groovy/lang/SpreadMap.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/lang/SpreadMap.java b/src/main/groovy/groovy/lang/SpreadMap.java
new file mode 100644
index 0000000..7ba9e4f
--- /dev/null
+++ b/src/main/groovy/groovy/lang/SpreadMap.java
@@ -0,0 +1,120 @@
+/*
+ *  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.lang;
+
+import org.codehaus.groovy.runtime.typehandling.DefaultTypeTransformation;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Helper to turn a list with an even number of elements into a Map.
+ * 
+ * @author Pilho Kim
+ * @author Tim Tiemens
+ */
+public class SpreadMap extends HashMap {
+    private int hashCode;
+
+    public SpreadMap(Object[] values) {
+        int i = 0;
+        while (i < values.length) {
+            super.put(values[i++], values[i++]);
+        }
+    }
+
+    public SpreadMap(Map map) {
+        super(map);
+    }
+
+    /**
+     * @since 1.8.0
+     * @param list the list to make spreadable
+     */
+    public SpreadMap(List list) {
+        this(list.toArray());
+    }
+
+    public Object put(Object key, Object value) {
+        throw new RuntimeException("SpreadMap: " + this + " is an immutable map, and so ("
+                                   + key + ": " + value + ") cannot be added.");
+    }
+
+    public Object remove(Object key) {
+        throw new RuntimeException("SpreadMap: " + this + " is an immutable map, and so the key ("
+                                   + key + ") cannot be deleted.");
+    }
+
+    public void putAll(Map t) {
+        throw new RuntimeException("SpreadMap: " + this + " is an immutable map, and so the map ("
+                                   + t + ") cannot be put in this spreadMap.");
+    }
+
+    public boolean equals(Object that) {
+        if (that instanceof SpreadMap) {
+            return equals((SpreadMap) that);
+        }
+        return false;
+    }
+
+    public boolean equals(SpreadMap that) {
+        if (that == null) return false;        
+
+        if (size() == that.size()) {
+            for (Object key : keySet()) {
+                if (!DefaultTypeTransformation.compareEqual(get(key), that.get(key))) {
+                    return false;
+                }
+            }
+            return true;
+        }
+        return false;
+    }
+
+    public int hashCode() {
+        if (hashCode == 0) {
+            for (Object key : keySet()) {
+                int hash = (key != null) ? key.hashCode() : 0xbabe;
+                hashCode ^= hash;
+            }
+        }
+        return hashCode;
+    }
+
+    /**
+     * @return the string expression of <code>this</code>
+     */
+    public String toString() {
+        if (isEmpty()) {
+            return "*:[:]";
+        }
+        StringBuilder sb = new StringBuilder("*:[");
+        Iterator iter = keySet().iterator();
+        while (iter.hasNext()) {
+            Object key = iter.next();
+            sb.append(key).append(":").append(get(key));
+            if (iter.hasNext())
+                sb.append(", ");
+        }
+        sb.append("]");
+        return sb.toString();
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/10110145/src/main/groovy/groovy/lang/SpreadMapEvaluatingException.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/lang/SpreadMapEvaluatingException.java b/src/main/groovy/groovy/lang/SpreadMapEvaluatingException.java
new file mode 100644
index 0000000..408a223
--- /dev/null
+++ b/src/main/groovy/groovy/lang/SpreadMapEvaluatingException.java
@@ -0,0 +1,25 @@
+/*
+ *  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.lang;
+
+public class SpreadMapEvaluatingException extends GroovyRuntimeException {
+    public SpreadMapEvaluatingException(String message) {
+        super(message);
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/10110145/src/main/groovy/groovy/lang/StringWriterIOException.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/lang/StringWriterIOException.java b/src/main/groovy/groovy/lang/StringWriterIOException.java
new file mode 100644
index 0000000..0372399
--- /dev/null
+++ b/src/main/groovy/groovy/lang/StringWriterIOException.java
@@ -0,0 +1,37 @@
+/*
+ *  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.lang;
+
+import java.io.IOException;
+
+/**
+ * An IO exception occurred trying to append to a StringWriter which should never happen.
+ * 
+ * @author <a href="mailto:james@coredevelopers.net">James Strachan</a>
+ */
+public class StringWriterIOException extends RuntimeException {
+
+    public StringWriterIOException(IOException e) {
+        super(e);
+    }
+
+    public IOException getIOException() {
+        return (IOException) getCause();
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/10110145/src/main/groovy/groovy/lang/TracingInterceptor.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/lang/TracingInterceptor.java b/src/main/groovy/groovy/lang/TracingInterceptor.java
new file mode 100644
index 0000000..f67de11
--- /dev/null
+++ b/src/main/groovy/groovy/lang/TracingInterceptor.java
@@ -0,0 +1,120 @@
+/*
+ *  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.lang;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.Writer;
+
+/*
+ * This {@link Interceptor} traces method calls on the proxied object to a log. 
+ * By default, the log is simply <pre>System.out</pre>; however, that can be 
+ * changed with the <pre>setWriter(Writer)</pre> method.
+ * <p>
+ * A message will be written to output before a method is invoked and after a method
+ * is invoked. If methods are nested, and invoke one another, then indentation 
+ * of two spaces is written.
+ * <p>
+ * Here is an example usage on the ArrayList object: <br>
+ * <pre class="groovyTestCase">
+ * def proxy = ProxyMetaClass.getInstance(ArrayList.class)
+ * proxy.interceptor = new TracingInterceptor()
+ * proxy.use {
+ *     def list = [1, 2, 3]
+ *     assert 3 == list.size()
+ *     assert list.contains(1)
+ * }
+ * </pre>
+ * Running this code produces this output: 
+ * <pre>
+ * before java.util.ArrayList.size()
+ * after  java.util.ArrayList.size()
+ * before java.util.ArrayList.contains(java.lang.Integer)
+ * after  java.util.ArrayList.contains(java.lang.Integer)
+ * </pre>
+ */
+public class TracingInterceptor implements Interceptor {
+
+    protected Writer writer = new PrintWriter(System.out);
+    private int indent = 0;
+
+    /**
+    * Returns the writer associated with this interceptor. 
+    */ 
+    public Writer getWriter() {
+        return writer;
+    }
+
+    /**
+    * Changes the writer associated with this interceptor. 
+    */ 
+    public void setWriter(Writer writer) {
+        this.writer = writer;
+    }
+
+    public Object beforeInvoke(Object object, String methodName, Object[] arguments) {
+        write(object, methodName, arguments, "before");
+        indent++ ;
+        return null;
+    }
+
+    public Object afterInvoke(Object object, String methodName, Object[] arguments, Object result) {
+        indent--;
+        write(object, methodName, arguments, "after ");
+        return result;
+    }
+
+    public boolean doInvoke() {
+        return true;
+    }
+    private String indent(){
+        StringBuilder result = new StringBuilder();
+        for (int i=0; i<indent;i++){
+            result.append("  ");
+        }
+        return result.toString();
+    }
+
+    protected void write(Object object, String methodName, Object[] arguments, final String origin) {
+        try {
+            writer.write(indent());
+            writer.write(origin);
+            writer.write(" ");
+            Class theClass = object instanceof Class ? (Class) object: object.getClass();
+            writeInfo(theClass, methodName, arguments);
+            writer.write("\n");
+            writer.flush();
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+    }
+
+    protected void writeInfo(final Class aClass, String methodName, Object[] arguments) throws IOException {
+        writer.write(aClass.getName());
+        writer.write(".");
+        writer.write(methodName);
+        writer.write("(");
+        for (int i = 0; i < arguments.length; i++) {
+            if (i > 0) writer.write(", ");
+            Object argument = arguments[i];
+            writer.write(argument.getClass().getName());
+        }
+        writer.write(")");
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/10110145/src/main/groovy/groovy/lang/TrampolineClosure.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/lang/TrampolineClosure.java b/src/main/groovy/groovy/lang/TrampolineClosure.java
new file mode 100644
index 0000000..ed68f00
--- /dev/null
+++ b/src/main/groovy/groovy/lang/TrampolineClosure.java
@@ -0,0 +1,111 @@
+/*
+ *  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.lang;
+
+/**
+ * A TrampolineClosure wraps a closure that needs to be executed on a functional trampoline.
+ * Upon calling, a TrampolineClosure will call the original closure waiting for its result.
+ * If the outcome of the call is another instance of a TrampolineClosure, created perhaps as a result to a call to the TrampolineClosure.trampoline()
+ * method, the TrampolineClosure will again be invoked. This repetitive invocation of returned TrampolineClosure instances will continue
+ * until a value other than TrampolineClosure is returned.
+ * That value will become the final result of the trampoline.
+ *
+ * @author Vaclav Pech
+ */
+final class TrampolineClosure<V> extends Closure<V> {
+
+    private final Closure<V> original;
+
+    TrampolineClosure(final Closure<V> original) {
+        super(original.getOwner(), original.getDelegate());
+        this.original = original;
+    }
+
+    /**
+     * Delegates to the wrapped closure
+     */
+    @Override
+    public int getMaximumNumberOfParameters() {
+        return original.maximumNumberOfParameters;
+    }
+
+    /**
+     * Delegates to the wrapped closure
+     */
+    @Override
+    public Class[] getParameterTypes() {
+        return original.parameterTypes;
+    }
+
+    /**
+     * Starts the trampoline loop and calls the wrapped closure as the first step.
+     * @return The final result of the trampoline
+     */
+    @Override
+    public V call() {
+        return loop(original.call());
+    }
+
+    /**
+     * Starts the trampoline loop and calls the wrapped closure as the first step.
+     * @return The final result of the trampoline
+     */
+    @Override
+    public V call(final Object arguments) {
+        return loop(original.call(arguments));
+    }
+
+    /**
+     * Starts the trampoline loop and calls the wrapped closure as the first step.
+     * @return The final result of the trampoline
+     */
+    @Override
+    public V call(final Object... args) {
+        return loop(original.call(args));
+    }
+
+    private V loop(final Object lastResult) {
+        Object result = lastResult;
+
+        for (;;) {
+            if (result instanceof TrampolineClosure) {
+                result = ((TrampolineClosure)result).original.call();
+            } else return (V) result;
+        }
+    }
+
+    /**
+     * Builds a trampolined variant of the current closure.
+     * @param args Parameters to curry to the underlying closure.
+     * @return An instance of TrampolineClosure wrapping the original closure after currying.
+     */
+    @Override
+   public Closure<V> trampoline(final Object... args) {
+        return new TrampolineClosure<V>(original.curry(args));
+    }
+
+    /**
+     * Returns itself, since it is a good enough trampolined variant of the current closure.
+     * @return An instance of TrampolineClosure wrapping the original closure.
+     */
+    @Override
+    public Closure<V> trampoline() {
+        return this;
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/10110145/src/main/groovy/groovy/lang/Tuple.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/lang/Tuple.java b/src/main/groovy/groovy/lang/Tuple.java
new file mode 100644
index 0000000..036d13e
--- /dev/null
+++ b/src/main/groovy/groovy/lang/Tuple.java
@@ -0,0 +1,85 @@
+/*
+ *  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.lang;
+
+import org.codehaus.groovy.runtime.typehandling.DefaultTypeTransformation;
+
+import java.io.Serializable;
+import java.util.AbstractList;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * Represents a list of Objects.
+ * 
+ * @author <a href="mailto:james@coredevelopers.net">James Strachan</a>
+ */
+public class Tuple<E> extends AbstractList<E> implements Serializable {
+    private static final long serialVersionUID = -6707770506387821031L;
+    private final E[] contents;
+
+    public Tuple(E... contents) {
+        if (contents == null) throw new NullPointerException();
+        this.contents = contents;
+    }
+
+    @Override
+    public E get(int index) {
+        return contents[index];
+    }
+
+    @Override
+    public int size() {
+        return contents.length;
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public List<E> subList(int fromIndex, int toIndex) {
+        int size = toIndex - fromIndex;
+        E[] newContent = (E[]) new Object[size];
+        System.arraycopy(contents, fromIndex, newContent, 0, size);
+        return new Tuple<>(newContent);
+    }
+
+    public Tuple<E> subTuple(int fromIndex, int toIndex) {
+        return (Tuple<E>) subList(fromIndex, toIndex);
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || !(o instanceof Tuple)) return false;
+
+        Tuple that = (Tuple) o;
+        int size = size();
+        if (size != that.size()) return false;
+        for (int i = 0; i < size; i++) {
+            if (!DefaultTypeTransformation.compareEqual(get(i), that.get(i))) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(contents);
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/10110145/src/main/groovy/groovy/lang/Tuple1.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/lang/Tuple1.java b/src/main/groovy/groovy/lang/Tuple1.java
new file mode 100644
index 0000000..9b8d6bd
--- /dev/null
+++ b/src/main/groovy/groovy/lang/Tuple1.java
@@ -0,0 +1,54 @@
+/*
+ *  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.lang;
+
+/**
+ * Represents a list of 1 typed Object.
+ *
+ * @since 2.5.0
+ */
+public class Tuple1<T1> extends Tuple {
+    private static final long serialVersionUID = -4647790147461409603L;
+    private final T1 first;
+
+    public Tuple1(T1 first) {
+        super(first);
+
+        this.first = first;
+    }
+
+    @Override
+    public Object get(int index) {
+        switch (index) {
+            case 0:
+                return first;
+            default:
+                throw new IndexOutOfBoundsException("index: " + index);
+        }
+    }
+
+    @Override
+    public int size() {
+        return 1;
+    }
+
+    public T1 getFirst() {
+        return first;
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/10110145/src/main/groovy/groovy/lang/Tuple2.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/lang/Tuple2.java b/src/main/groovy/groovy/lang/Tuple2.java
new file mode 100644
index 0000000..b096aee
--- /dev/null
+++ b/src/main/groovy/groovy/lang/Tuple2.java
@@ -0,0 +1,60 @@
+/*
+ *  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.lang;
+
+/**
+ * Represents a list of 2 typed Objects.
+ */
+public class Tuple2<T1, T2> extends Tuple {
+    private static final long serialVersionUID = 9006144674906325597L;
+    private final T1 first;
+    private final T2 second;
+
+    public Tuple2(T1 first, T2 second) {
+        super(first, second);
+
+        this.first = first;
+        this.second = second;
+    }
+
+    @Override
+    public Object get(int index) {
+        switch (index) {
+            case 0:
+                return first;
+            case 1:
+                return second;
+            default:
+                throw new IndexOutOfBoundsException("index: " + index);
+        }
+    }
+
+    @Override
+    public int size() {
+        return 2;
+    }
+
+    public T1 getFirst() {
+        return first;
+    }
+
+    public T2 getSecond() {
+        return second;
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/10110145/src/main/groovy/groovy/lang/Tuple3.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/lang/Tuple3.java b/src/main/groovy/groovy/lang/Tuple3.java
new file mode 100644
index 0000000..b5fe7d9
--- /dev/null
+++ b/src/main/groovy/groovy/lang/Tuple3.java
@@ -0,0 +1,71 @@
+/*
+ *  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.lang;
+
+/**
+ * Represents a list of 3 typed Objects.
+ *
+ * @since 2.5.0
+ */
+public class Tuple3<T1, T2, T3> extends Tuple {
+    private static final long serialVersionUID = 8469774237154310687L;
+    private final T1 first;
+    private final T2 second;
+    private final T3 third;
+
+    public Tuple3(T1 first, T2 second, T3 third) {
+        super(first, second, third);
+
+        this.first = first;
+        this.second = second;
+        this.third = third;
+    }
+
+    @Override
+    public Object get(int index) {
+        switch (index) {
+            case 0:
+                return first;
+            case 1:
+                return second;
+            case 2:
+                return third;
+            default:
+                throw new IndexOutOfBoundsException("index: " + index);
+        }
+    }
+
+    @Override
+    public int size() {
+        return 3;
+    }
+
+    public T1 getFirst() {
+        return first;
+    }
+
+    public T2 getSecond() {
+        return second;
+    }
+
+    public T3 getThird() {
+        return third;
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/10110145/src/main/groovy/groovy/lang/Tuple4.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/lang/Tuple4.java b/src/main/groovy/groovy/lang/Tuple4.java
new file mode 100644
index 0000000..04f414e
--- /dev/null
+++ b/src/main/groovy/groovy/lang/Tuple4.java
@@ -0,0 +1,79 @@
+/*
+ *  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.lang;
+
+/**
+ * Represents a list of 4 typed Objects.
+ *
+ * @since 2.5.0
+ */
+public class Tuple4<T1, T2, T3, T4> extends Tuple {
+    private static final long serialVersionUID = -7788878731471377207L;
+    private final T1 first;
+    private final T2 second;
+    private final T3 third;
+    private final T4 fourth;
+
+    public Tuple4(T1 first, T2 second, T3 third, T4 fourth) {
+        super(first, second, third, fourth);
+
+        this.first = first;
+        this.second = second;
+        this.third = third;
+        this.fourth = fourth;
+    }
+
+    @Override
+    public Object get(int index) {
+        switch (index) {
+            case 0:
+                return first;
+            case 1:
+                return second;
+            case 2:
+                return third;
+            case 3:
+                return fourth;
+            default:
+                throw new IndexOutOfBoundsException("index: " + index);
+        }
+    }
+
+    @Override
+    public int size() {
+        return 4;
+    }
+
+    public T1 getFirst() {
+        return first;
+    }
+
+    public T2 getSecond() {
+        return second;
+    }
+
+    public T3 getThird() {
+        return third;
+    }
+
+    public T4 getFourth() {
+        return fourth;
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/10110145/src/main/groovy/groovy/lang/Tuple5.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/lang/Tuple5.java b/src/main/groovy/groovy/lang/Tuple5.java
new file mode 100644
index 0000000..ee9c802
--- /dev/null
+++ b/src/main/groovy/groovy/lang/Tuple5.java
@@ -0,0 +1,87 @@
+/*
+ *  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.lang;
+
+/**
+ * Represents a list of 5 typed Objects.
+ *
+ * @since 2.5.0
+ */
+public class Tuple5<T1, T2, T3, T4, T5> extends Tuple {
+    private static final long serialVersionUID = 6722094358774027115L;
+    private final T1 first;
+    private final T2 second;
+    private final T3 third;
+    private final T4 fourth;
+    private final T5 fifth;
+
+    public Tuple5(T1 first, T2 second, T3 third, T4 fourth, T5 fifth) {
+        super(first, second, third, fourth, fifth);
+
+        this.first = first;
+        this.second = second;
+        this.third = third;
+        this.fourth = fourth;
+        this.fifth = fifth;
+    }
+
+    @Override
+    public Object get(int index) {
+        switch (index) {
+            case 0:
+                return first;
+            case 1:
+                return second;
+            case 2:
+                return third;
+            case 3:
+                return fourth;
+            case 4:
+                return fifth;
+            default:
+                throw new IndexOutOfBoundsException("index: " + index);
+        }
+    }
+
+    @Override
+    public int size() {
+        return 5;
+    }
+
+    public T1 getFirst() {
+        return first;
+    }
+
+    public T2 getSecond() {
+        return second;
+    }
+
+    public T3 getThird() {
+        return third;
+    }
+
+    public T4 getFourth() {
+        return fourth;
+    }
+
+    public T5 getFifth() {
+        return fifth;
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/10110145/src/main/groovy/groovy/lang/Tuple6.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/lang/Tuple6.java b/src/main/groovy/groovy/lang/Tuple6.java
new file mode 100644
index 0000000..76d12ca
--- /dev/null
+++ b/src/main/groovy/groovy/lang/Tuple6.java
@@ -0,0 +1,95 @@
+/*
+ *  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.lang;
+
+/**
+ * Represents a list of 6 typed Objects.
+ *
+ * @since 2.5.0
+ */
+public class Tuple6<T1, T2, T3, T4, T5, T6> extends Tuple {
+    private static final long serialVersionUID = -7848588473093102288L;
+    private final T1 first;
+    private final T2 second;
+    private final T3 third;
+    private final T4 fourth;
+    private final T5 fifth;
+    private final T6 sixth;
+
+    public Tuple6(T1 first, T2 second, T3 third, T4 fourth, T5 fifth, T6 sixth) {
+        super(first, second, third, fourth, fifth, sixth);
+
+        this.first = first;
+        this.second = second;
+        this.third = third;
+        this.fourth = fourth;
+        this.fifth = fifth;
+        this.sixth = sixth;
+    }
+
+    @Override
+    public Object get(int index) {
+        switch (index) {
+            case 0:
+                return first;
+            case 1:
+                return second;
+            case 2:
+                return third;
+            case 3:
+                return fourth;
+            case 4:
+                return fifth;
+            case 5:
+                return sixth;
+            default:
+                throw new IndexOutOfBoundsException("index: " + index);
+        }
+    }
+
+    @Override
+    public int size() {
+        return 6;
+    }
+
+    public T1 getFirst() {
+        return first;
+    }
+
+    public T2 getSecond() {
+        return second;
+    }
+
+    public T3 getThird() {
+        return third;
+    }
+
+    public T4 getFourth() {
+        return fourth;
+    }
+
+    public T5 getFifth() {
+        return fifth;
+    }
+
+    public T6 getSixth() {
+        return sixth;
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/10110145/src/main/groovy/groovy/lang/Tuple7.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/lang/Tuple7.java b/src/main/groovy/groovy/lang/Tuple7.java
new file mode 100644
index 0000000..05046e7
--- /dev/null
+++ b/src/main/groovy/groovy/lang/Tuple7.java
@@ -0,0 +1,103 @@
+/*
+ *  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.lang;
+
+/**
+ * Represents a list of 7 typed Objects.
+ *
+ * @since 2.5.0
+ */
+public class Tuple7<T1, T2, T3, T4, T5, T6, T7> extends Tuple {
+    private static final long serialVersionUID = 4226144828786865766L;
+    private final T1 first;
+    private final T2 second;
+    private final T3 third;
+    private final T4 fourth;
+    private final T5 fifth;
+    private final T6 sixth;
+    private final T7 seventh;
+
+    public Tuple7(T1 first, T2 second, T3 third, T4 fourth, T5 fifth, T6 sixth, T7 seventh) {
+        super(first, second, third, fourth, fifth, sixth, seventh);
+
+        this.first = first;
+        this.second = second;
+        this.third = third;
+        this.fourth = fourth;
+        this.fifth = fifth;
+        this.sixth = sixth;
+        this.seventh = seventh;
+    }
+
+    @Override
+    public Object get(int index) {
+        switch (index) {
+            case 0:
+                return first;
+            case 1:
+                return second;
+            case 2:
+                return third;
+            case 3:
+                return fourth;
+            case 4:
+                return fifth;
+            case 5:
+                return sixth;
+            case 6:
+                return seventh;
+            default:
+                throw new IndexOutOfBoundsException("index: " + index);
+        }
+    }
+
+    @Override
+    public int size() {
+        return 7;
+    }
+
+    public T1 getFirst() {
+        return first;
+    }
+
+    public T2 getSecond() {
+        return second;
+    }
+
+    public T3 getThird() {
+        return third;
+    }
+
+    public T4 getFourth() {
+        return fourth;
+    }
+
+    public T5 getFifth() {
+        return fifth;
+    }
+
+    public T6 getSixth() {
+        return sixth;
+    }
+
+    public T7 getSeventh() {
+        return seventh;
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/10110145/src/main/groovy/groovy/lang/Tuple8.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/lang/Tuple8.java b/src/main/groovy/groovy/lang/Tuple8.java
new file mode 100644
index 0000000..1f38ca9
--- /dev/null
+++ b/src/main/groovy/groovy/lang/Tuple8.java
@@ -0,0 +1,111 @@
+/*
+ *  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.lang;
+
+/**
+ * Represents a list of 8 typed Objects.
+ *
+ * @since 2.5.0
+ */
+public class Tuple8<T1, T2, T3, T4, T5, T6, T7, T8> extends Tuple {
+    private static final long serialVersionUID = -8895822084644138566L;
+    private final T1 first;
+    private final T2 second;
+    private final T3 third;
+    private final T4 fourth;
+    private final T5 fifth;
+    private final T6 sixth;
+    private final T7 seventh;
+    private final T8 eighth;
+
+    public Tuple8(T1 first, T2 second, T3 third, T4 fourth, T5 fifth, T6 sixth, T7 seventh, T8 eighth) {
+        super(first, second, third, fourth, fifth, sixth, seventh, eighth);
+
+        this.first = first;
+        this.second = second;
+        this.third = third;
+        this.fourth = fourth;
+        this.fifth = fifth;
+        this.sixth = sixth;
+        this.seventh = seventh;
+        this.eighth = eighth;
+    }
+
+    @Override
+    public Object get(int index) {
+        switch (index) {
+            case 0:
+                return first;
+            case 1:
+                return second;
+            case 2:
+                return third;
+            case 3:
+                return fourth;
+            case 4:
+                return fifth;
+            case 5:
+                return sixth;
+            case 6:
+                return seventh;
+            case 7:
+                return eighth;
+            default:
+                throw new IndexOutOfBoundsException("index: " + index);
+        }
+    }
+
+    @Override
+    public int size() {
+        return 8;
+    }
+
+    public T1 getFirst() {
+        return first;
+    }
+
+    public T2 getSecond() {
+        return second;
+    }
+
+    public T3 getThird() {
+        return third;
+    }
+
+    public T4 getFourth() {
+        return fourth;
+    }
+
+    public T5 getFifth() {
+        return fifth;
+    }
+
+    public T6 getSixth() {
+        return sixth;
+    }
+
+    public T7 getSeventh() {
+        return seventh;
+    }
+
+    public T8 getEighth() {
+        return eighth;
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/10110145/src/main/groovy/groovy/lang/Tuple9.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/lang/Tuple9.java b/src/main/groovy/groovy/lang/Tuple9.java
new file mode 100644
index 0000000..3189c10
--- /dev/null
+++ b/src/main/groovy/groovy/lang/Tuple9.java
@@ -0,0 +1,120 @@
+/*
+ *  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.lang;
+
+/**
+ * Represents a list of 9 typed Objects.
+ *
+ * @since 2.5.0
+ */
+public class Tuple9<T1, T2, T3, T4, T5, T6, T7, T8, T9> extends Tuple {
+    private static final long serialVersionUID = -5181196675351911769L;
+    private final T1 first;
+    private final T2 second;
+    private final T3 third;
+    private final T4 fourth;
+    private final T5 fifth;
+    private final T6 sixth;
+    private final T7 seventh;
+    private final T8 eighth;
+    private final T9 ninth;
+
+    public Tuple9(T1 first, T2 second, T3 third, T4 fourth, T5 fifth, T6 sixth, T7 seventh, T8 eighth, T9 ninth) {
+        super(first, second, third, fourth, fifth, sixth, seventh, eighth, ninth);
+
+        this.first = first;
+        this.second = second;
+        this.third = third;
+        this.fourth = fourth;
+        this.fifth = fifth;
+        this.sixth = sixth;
+        this.seventh = seventh;
+        this.eighth = eighth;
+        this.ninth = ninth;
+    }
+
+    @Override
+    public Object get(int index) {
+        switch (index) {
+            case 0:
+                return first;
+            case 1:
+                return second;
+            case 2:
+                return third;
+            case 3:
+                return fourth;
+            case 4:
+                return fifth;
+            case 5:
+                return sixth;
+            case 6:
+                return seventh;
+            case 7:
+                return eighth;
+            case 8:
+                return ninth;
+            default:
+                throw new IndexOutOfBoundsException("index: " + index);
+        }
+    }
+
+    @Override
+    public int size() {
+        return 9;
+    }
+
+    public T1 getFirst() {
+        return first;
+    }
+
+    public T2 getSecond() {
+        return second;
+    }
+
+    public T3 getThird() {
+        return third;
+    }
+
+    public T4 getFourth() {
+        return fourth;
+    }
+
+    public T5 getFifth() {
+        return fifth;
+    }
+
+    public T6 getSixth() {
+        return sixth;
+    }
+
+    public T7 getSeventh() {
+        return seventh;
+    }
+
+    public T8 getEighth() {
+        return eighth;
+    }
+
+    public T9 getNinth() {
+        return ninth;
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/10110145/src/main/groovy/groovy/lang/Writable.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/lang/Writable.java b/src/main/groovy/groovy/lang/Writable.java
new file mode 100644
index 0000000..ec135cd
--- /dev/null
+++ b/src/main/groovy/groovy/lang/Writable.java
@@ -0,0 +1,56 @@
+/*
+ *  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.lang;
+
+import java.io.IOException;
+import java.io.Writer;
+
+
+/**
+ * Represents an object which is capable of writing itself to a text stream
+ * in a more efficient format than just creating a toString() representation
+ * of itself. This mechanism is particularly useful for templates and such like.
+ * <p>
+ * It is worth noting that writable implementations often override their
+ * toString() implementation as well to allow rendering the same result 
+ * directly to a String; however this is not required.
+ *
+ * @author <a href="mailto:james@coredevelopers.net">James Strachan</a>
+ */
+public interface Writable {
+
+    /**
+     * Writes this object to the given writer.
+     * <p>
+     * This is used to defer content creation until the point when it is
+     * streamed to the output destination.  Oftentimes, content will be defined 
+     * but not necessarily created (as is may be the case with a Closure 
+     * definition.)  In that case, the output is then 'deferred' to the point 
+     * when it is serialized to the writer. This class may be used whenever an 
+     * object should be responsible for creating its own textual representation, 
+     * but creating the entire output as a single String would be inefficient
+     * (such as outputting a multi-gigabyte XML document.)
+     * 
+     * @param out the Writer to which this Writable should output its data.
+     * @return the Writer that was passed
+     * @throws IOException if an error occurred while outputting data to the writer
+     */
+    Writer writeTo(Writer out) throws IOException;
+        
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/10110145/src/main/groovy/groovy/lang/groovydoc/Groovydoc.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/lang/groovydoc/Groovydoc.java b/src/main/groovy/groovy/lang/groovydoc/Groovydoc.java
new file mode 100644
index 0000000..d7d4204
--- /dev/null
+++ b/src/main/groovy/groovy/lang/groovydoc/Groovydoc.java
@@ -0,0 +1,96 @@
+/*
+ *  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.lang.groovydoc;
+
+import java.lang.reflect.AnnotatedElement;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * Represents groovydoc
+ */
+public class Groovydoc {
+    private final String content;
+    private List<GroovydocTag> tagList;
+    private final GroovydocHolder holder;
+
+    public Groovydoc(String content, GroovydocHolder groovydocHolder) {
+        this.content = content;
+        this.holder = groovydocHolder;
+    }
+
+    public Groovydoc(final String content, final AnnotatedElement annotatedElement) {
+        this.content = content;
+        this.holder = new GroovydocHolder<AnnotatedElement>() {
+            @Override
+            public Groovydoc getGroovydoc() {
+                return Groovydoc.this;
+            }
+
+            @Override
+            public AnnotatedElement getInstance() {
+                return annotatedElement;
+            }
+        };
+    }
+
+    /**
+     * Get the content of groovydoc
+     * @return the text content
+     */
+    public String getContent() {
+        return content;
+    }
+
+    /**
+     * TODO Get list of groovydoc tags
+     * @return a list of tags
+     */
+    public List<GroovydocTag> getTagList() {
+        throw new UnsupportedOperationException("[TODO]parsing tags will be a new features of the next releases");
+//        return tagList;
+    }
+
+    /**
+     * Get the holder of the groovydoc
+     * @return the groovydoc holder
+     */
+    public GroovydocHolder getHolder() {
+        return holder;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+        Groovydoc groovydoc = (Groovydoc) o;
+        return Objects.equals(content, groovydoc.content) &&
+                Objects.equals(holder, groovydoc.holder);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(content, holder);
+    }
+
+    @Override
+    public String toString() {
+        return this.content;
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/10110145/src/main/groovy/groovy/lang/groovydoc/GroovydocHolder.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/lang/groovydoc/GroovydocHolder.java b/src/main/groovy/groovy/lang/groovydoc/GroovydocHolder.java
new file mode 100644
index 0000000..eb41df4
--- /dev/null
+++ b/src/main/groovy/groovy/lang/groovydoc/GroovydocHolder.java
@@ -0,0 +1,37 @@
+/*
+ *  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.lang.groovydoc;
+
+/**
+ * Represents Groovydoc Holder
+ */
+public interface GroovydocHolder<T> {
+    String DOC_COMMENT = "_DOC_COMMENT"; // keys for meta data
+    /**
+     * Get the groovydoc
+     * @return the groovydoc
+     */
+    Groovydoc getGroovydoc();
+
+    /**
+     * Get GroovydocHolder instance
+     * @return GroovydocHolder instance
+     */
+    T getInstance();
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/10110145/src/main/groovy/groovy/lang/groovydoc/GroovydocTag.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/lang/groovydoc/GroovydocTag.java b/src/main/groovy/groovy/lang/groovydoc/GroovydocTag.java
new file mode 100644
index 0000000..14e5aaa
--- /dev/null
+++ b/src/main/groovy/groovy/lang/groovydoc/GroovydocTag.java
@@ -0,0 +1,68 @@
+/*
+ *  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.lang.groovydoc;
+
+import java.util.Objects;
+
+/**
+ * TODO parse groovydoc to get tag content
+ */
+public class GroovydocTag {
+    private String name;
+    private String content;
+    private Groovydoc groovydoc;
+
+    public GroovydocTag(String name, String content, Groovydoc groovydoc) {
+        this.name = name;
+        this.content = content;
+        this.groovydoc = groovydoc;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public String getContent() {
+        return content;
+    }
+
+    public Groovydoc getGroovydoc() {
+        return groovydoc;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+        GroovydocTag that = (GroovydocTag) o;
+        return Objects.equals(name, that.name) &&
+                Objects.equals(content, that.content) &&
+                Objects.equals(groovydoc, that.groovydoc);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(name, content, groovydoc);
+    }
+
+    @Override
+    public String toString() {
+        return content;
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/10110145/src/main/groovy/groovy/lang/package.html
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/lang/package.html b/src/main/groovy/groovy/lang/package.html
new file mode 100644
index 0000000..1ea84fc
--- /dev/null
+++ b/src/main/groovy/groovy/lang/package.html
@@ -0,0 +1,28 @@
+<!--
+
+     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.lang.*</title>
+  </head>
+  <body>
+    <p>Core Groovy language classes for implementing data structures, closures, metadata and so forth.</p>
+  </body>
+</html>

http://git-wip-us.apache.org/repos/asf/groovy/blob/10110145/src/main/groovy/groovy/org/codehaus/groovy/transform/ASTTestTransformation.groovy
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/org/codehaus/groovy/transform/ASTTestTransformation.groovy b/src/main/groovy/groovy/org/codehaus/groovy/transform/ASTTestTransformation.groovy
new file mode 100644
index 0000000..dcfe314
--- /dev/null
+++ b/src/main/groovy/groovy/org/codehaus/groovy/transform/ASTTestTransformation.groovy
@@ -0,0 +1,233 @@
+/*
+ *  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
+
+import groovy.transform.CompilationUnitAware
+import org.codehaus.groovy.ast.ASTNode
+import org.codehaus.groovy.ast.AnnotationNode
+import org.codehaus.groovy.ast.ClassCodeVisitorSupport
+import org.codehaus.groovy.ast.ClassHelper
+import org.codehaus.groovy.ast.ClassNode
+import org.codehaus.groovy.ast.MethodNode
+import org.codehaus.groovy.ast.expr.ClosureExpression
+import org.codehaus.groovy.ast.expr.PropertyExpression
+import org.codehaus.groovy.ast.expr.VariableExpression
+import org.codehaus.groovy.ast.stmt.Statement
+import org.codehaus.groovy.control.CompilationUnit
+import org.codehaus.groovy.control.CompilePhase
+import org.codehaus.groovy.control.CompilerConfiguration
+import org.codehaus.groovy.control.ErrorCollector
+import org.codehaus.groovy.control.Janitor
+import org.codehaus.groovy.control.ProcessingUnit
+import org.codehaus.groovy.control.SourceUnit
+import org.codehaus.groovy.control.customizers.ImportCustomizer
+import org.codehaus.groovy.control.io.ReaderSource
+import org.codehaus.groovy.runtime.MethodClosure
+import org.codehaus.groovy.syntax.SyntaxException
+import org.codehaus.groovy.tools.Utilities
+
+import static org.codehaus.groovy.ast.tools.GeneralUtils.classX
+import static org.codehaus.groovy.ast.tools.GeneralUtils.propX
+
+@GroovyASTTransformation(phase = CompilePhase.SEMANTIC_ANALYSIS)
+class ASTTestTransformation extends AbstractASTTransformation implements CompilationUnitAware {
+    private CompilationUnit compilationUnit
+
+    void visit(final ASTNode[] nodes, final SourceUnit source) {
+        AnnotationNode annotationNode = nodes[0]
+        def member = annotationNode.getMember('phase')
+        def phase = null
+        if (member) {
+            if (member instanceof VariableExpression) {
+                phase = CompilePhase.valueOf(member.text)
+            } else if (member instanceof PropertyExpression) {
+                phase = CompilePhase.valueOf(member.propertyAsString)
+            }
+            annotationNode.setMember('phase', propX(classX(ClassHelper.make(CompilePhase)), phase.toString()))
+        }
+        member = annotationNode.getMember('value')
+        if (member && !(member instanceof ClosureExpression)) {
+            throw new SyntaxException("ASTTest value must be a closure", member.getLineNumber(), member.getColumnNumber())
+        }
+        if (!member && !annotationNode.getNodeMetaData(ASTTestTransformation)) {
+            throw new SyntaxException("Missing test expression", annotationNode.getLineNumber(), annotationNode.getColumnNumber())
+        }
+        // convert value into node metadata so that the expression doesn't mix up with other AST xforms like type checking
+        annotationNode.putNodeMetaData(ASTTestTransformation, member)
+        annotationNode.getMembers().remove('value')
+
+        def pcallback = compilationUnit.progressCallback
+        def callback = new CompilationUnit.ProgressCallback() {
+            Binding binding = new Binding([:].withDefault {null})
+
+            @Override
+            void call(final ProcessingUnit context, final int phaseRef) {
+                if (phase==null ||  phaseRef == phase.phaseNumber) {
+                    ClosureExpression testClosure = nodes[0].getNodeMetaData(ASTTestTransformation)
+                    StringBuilder sb = new StringBuilder()
+                    for (int i = testClosure.lineNumber; i <= testClosure.lastLineNumber; i++) {
+                        sb.append(source.source.getLine(i, new Janitor())).append('\n')
+                    }
+                    def testSource = sb.substring(testClosure.columnNumber + 1, sb.length())
+                    testSource = testSource.substring(0, testSource.lastIndexOf('}'))
+                    CompilerConfiguration config = new CompilerConfiguration()
+                    def customizer = new ImportCustomizer()
+                    config.addCompilationCustomizers(customizer)
+                    binding['sourceUnit'] = source
+                    binding['node'] = nodes[1]
+                    binding['lookup'] = new MethodClosure(LabelFinder, "lookup").curry(nodes[1])
+                    binding['compilationUnit'] = compilationUnit
+                    binding['compilePhase'] = CompilePhase.fromPhaseNumber(phaseRef)
+
+                    GroovyShell shell = new GroovyShell(binding, config)
+
+                    source.AST.imports.each {
+                        customizer.addImport(it.alias, it.type.name)
+                    }
+                    source.AST.starImports.each {
+                        customizer.addStarImports(it.packageName)
+                    }
+                    source.AST.staticImports.each {
+                        customizer.addStaticImport(it.value.alias, it.value.type.name, it.value.fieldName)
+                    }
+                    source.AST.staticStarImports.each {
+                        customizer.addStaticStars(it.value.className)
+                    }
+                    shell.evaluate(testSource)
+                }
+            }
+        }
+        
+        if (pcallback!=null) {
+            if (pcallback instanceof ProgressCallbackChain) {
+                pcallback.addCallback(callback)                
+            } else {
+                pcallback = new ProgressCallbackChain(pcallback, callback)
+            }
+            callback = pcallback
+        }
+        
+        compilationUnit.setProgressCallback(callback)
+
+    }
+
+    void setCompilationUnit(final CompilationUnit unit) {
+        this.compilationUnit = unit
+    }
+
+    private static class AssertionSourceDelegatingSourceUnit extends SourceUnit {
+        private final ReaderSource delegate
+
+        AssertionSourceDelegatingSourceUnit(final String name, final ReaderSource source, final CompilerConfiguration flags, final GroovyClassLoader loader, final ErrorCollector er) {
+            super(name, '', flags, loader, er)
+            delegate = source
+        }
+
+        @Override
+        String getSample(final int line, final int column, final Janitor janitor) {
+            String sample = null;
+            String text = delegate.getLine(line, janitor);
+
+            if (text != null) {
+                if (column > 0) {
+                    String marker = Utilities.repeatString(" ", column - 1) + "^";
+
+                    if (column > 40) {
+                        int start = column - 30 - 1;
+                        int end = (column + 10 > text.length() ? text.length() : column + 10 - 1);
+                        sample = "   " + text.substring(start, end) + Utilities.eol() + "   " +
+                                marker.substring(start, marker.length());
+                    } else {
+                        sample = "   " + text + Utilities.eol() + "   " + marker;
+                    }
+                } else {
+                    sample = text;
+                }
+            }
+
+            return sample;
+
+        }
+
+    }
+    
+    private static class ProgressCallbackChain extends CompilationUnit.ProgressCallback {
+
+        private final List<CompilationUnit.ProgressCallback> chain = new LinkedList<CompilationUnit.ProgressCallback>()
+
+        ProgressCallbackChain(CompilationUnit.ProgressCallback... callbacks) {
+            if (callbacks!=null) {
+                callbacks.each { addCallback(it) }
+            }
+        }
+
+        public void addCallback(CompilationUnit.ProgressCallback callback) {
+            chain << callback
+        }
+        
+        @Override
+        void call(final ProcessingUnit context, final int phase) {
+            chain*.call(context, phase)
+        }
+    }
+
+    public static class LabelFinder extends ClassCodeVisitorSupport {
+
+        public static List<Statement> lookup(MethodNode node, String label) {
+            LabelFinder finder = new LabelFinder(label, null)
+            node.code.visit(finder)
+
+            finder.targets
+        }
+
+        public static List<Statement> lookup(ClassNode node, String label) {
+            LabelFinder finder = new LabelFinder(label, null)
+            node.methods*.code*.visit(finder)
+            node.declaredConstructors*.code*.visit(finder)
+
+            finder.targets
+        }
+
+        private final String label
+        private final SourceUnit unit
+
+        private final List<Statement> targets = new LinkedList<Statement>();
+
+        LabelFinder(final String label, final SourceUnit unit) {
+            this.label = label
+            this.unit = unit;
+        }
+
+        @Override
+        protected SourceUnit getSourceUnit() {
+            unit
+        }
+
+        @Override
+        protected void visitStatement(final Statement statement) {
+            super.visitStatement(statement)
+            if (statement.statementLabel==label) targets << statement
+        }
+
+        List<Statement> getTargets() {
+            return Collections.unmodifiableList(targets)
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/10110145/src/main/groovy/groovy/org/codehaus/groovy/transform/ConditionalInterruptibleASTTransformation.groovy
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/org/codehaus/groovy/transform/ConditionalInterruptibleASTTransformation.groovy b/src/main/groovy/groovy/org/codehaus/groovy/transform/ConditionalInterruptibleASTTransformation.groovy
new file mode 100644
index 0000000..2cda121
--- /dev/null
+++ b/src/main/groovy/groovy/org/codehaus/groovy/transform/ConditionalInterruptibleASTTransformation.groovy
@@ -0,0 +1,145 @@
+/*
+ *  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
+
+import groovy.transform.ConditionalInterrupt
+import org.codehaus.groovy.ast.AnnotatedNode
+import org.codehaus.groovy.ast.AnnotationNode
+import org.codehaus.groovy.ast.ClassHelper
+import org.codehaus.groovy.ast.ClassNode
+import org.codehaus.groovy.ast.FieldNode
+import org.codehaus.groovy.ast.MethodNode
+import org.codehaus.groovy.ast.Parameter
+import org.codehaus.groovy.ast.PropertyNode
+import org.codehaus.groovy.ast.expr.ArgumentListExpression
+import org.codehaus.groovy.ast.expr.ClosureExpression
+import org.codehaus.groovy.ast.expr.Expression
+import org.codehaus.groovy.ast.expr.MethodCallExpression
+import org.codehaus.groovy.ast.expr.VariableExpression
+import org.codehaus.groovy.ast.tools.ClosureUtils
+import org.codehaus.groovy.control.CompilePhase
+
+/**
+ * Allows "interrupt-safe" executions of scripts by adding a custom conditional
+ * check on loops (for, while, do) and first statement of closures. By default, also adds an interrupt check
+ * statement on the beginning of method calls.
+ *
+ * @see groovy.transform.ConditionalInterrupt
+ * @author Cedric Champeau
+ * @author Hamlet D'Arcy
+ * @author Paul King
+ * @since 1.8.0
+ */
+@GroovyASTTransformation(phase = CompilePhase.CANONICALIZATION)
+public class ConditionalInterruptibleASTTransformation extends AbstractInterruptibleASTTransformation {
+
+  private static final ClassNode MY_TYPE = ClassHelper.make(ConditionalInterrupt)
+
+  private ClosureExpression conditionNode
+  private String conditionMethod
+  private MethodCallExpression conditionCallExpression
+  private ClassNode currentClass
+
+  protected ClassNode type() {
+    return MY_TYPE
+  }
+
+  protected void setupTransform(AnnotationNode node) {
+    super.setupTransform(node)
+    def member = node.getMember("value")
+    if (!member || !(member instanceof ClosureExpression)) internalError("Expected closure value for annotation parameter 'value'. Found $member")
+    conditionNode = member;
+    conditionMethod = 'conditionalTransform' + node.hashCode() + '$condition'
+    conditionCallExpression = new MethodCallExpression(new VariableExpression('this'), conditionMethod, new ArgumentListExpression())
+  }
+
+  protected String getErrorMessage() {
+    'Execution interrupted. The following condition failed: ' + convertClosureToSource(conditionNode)
+  }
+
+  void visitClass(ClassNode type) {
+    currentClass = type
+    def method = type.addMethod(conditionMethod, ACC_PRIVATE | ACC_SYNTHETIC, ClassHelper.OBJECT_TYPE, Parameter.EMPTY_ARRAY, ClassNode.EMPTY_ARRAY, conditionNode.code)
+    method.synthetic = true
+    if (applyToAllMembers) {
+      super.visitClass(type)
+    }
+  }
+
+  protected Expression createCondition() {
+    conditionCallExpression
+  }
+
+  @Override
+  void visitAnnotations(AnnotatedNode node) {
+    // this transformation does not apply on annotation nodes
+    // visiting could lead to stack overflows
+  }
+
+  @Override
+  void visitField(FieldNode node) {
+    if (!node.isStatic() && !node.isSynthetic()) {
+      super.visitField node
+    }
+  }
+
+  @Override
+  void visitProperty(PropertyNode node) {
+    if (!node.isStatic() && !node.isSynthetic()) {
+      super.visitProperty node
+    }
+  }
+
+  @Override
+  void visitClosureExpression(ClosureExpression closureExpr) {
+    if (closureExpr == conditionNode) return // do not visit the closure from the annotation itself
+    def code = closureExpr.code
+    closureExpr.code = wrapBlock(code)
+    super.visitClosureExpression closureExpr
+  }
+
+  @Override
+  void visitMethod(MethodNode node) {
+    if (node.name == conditionMethod && !node.isSynthetic()) return // do not visit the generated method
+    if (node.name == 'run' && currentClass.isScript() && node.parameters.length == 0) {
+      // the run() method should not have the statement added, otherwise the script binding won't be set before
+      // the condition is actually tested
+      super.visitMethod(node)
+    } else {
+      if (checkOnMethodStart && !node.isSynthetic() && !node.isStatic() && !node.isAbstract()) {
+        def code = node.code
+        node.code = wrapBlock(code);
+      }
+      if (!node.isSynthetic() && !node.isStatic()) super.visitMethod(node)
+    }
+  }
+
+  /**
+   * Converts a ClosureExpression into the String source.
+   * @param expression a closure
+   * @return the source the closure was created from
+   */
+  private String convertClosureToSource(ClosureExpression expression) {
+    try {
+        return ClosureUtils.convertClosureToSource(this.source.source, expression);
+    } catch(Exception e) {
+        return e.message
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/10110145/src/main/groovy/groovy/org/codehaus/groovy/transform/ThreadInterruptibleASTTransformation.groovy
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/org/codehaus/groovy/transform/ThreadInterruptibleASTTransformation.groovy b/src/main/groovy/groovy/org/codehaus/groovy/transform/ThreadInterruptibleASTTransformation.groovy
new file mode 100644
index 0000000..a4fb4c3
--- /dev/null
+++ b/src/main/groovy/groovy/org/codehaus/groovy/transform/ThreadInterruptibleASTTransformation.groovy
@@ -0,0 +1,98 @@
+/*
+ *  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
+
+import groovy.transform.CompileStatic
+import groovy.transform.ThreadInterrupt
+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.ArgumentListExpression
+import org.codehaus.groovy.ast.expr.ClassExpression
+import org.codehaus.groovy.ast.expr.ClosureExpression
+import org.codehaus.groovy.ast.expr.Expression
+import org.codehaus.groovy.ast.expr.MethodCallExpression
+import org.codehaus.groovy.control.CompilePhase
+
+/**
+ * Allows "interrupt-safe" executions of scripts by adding Thread.currentThread().isInterrupted()
+ * checks on loops (for, while, do) and first statement of closures. By default, also adds an interrupt check
+ * statement on the beginning of method calls.
+ *
+ * @see groovy.transform.ThreadInterrupt
+ *
+ * @author Cedric Champeau
+ * @author Hamlet D'Arcy
+ *
+ * @since 1.8.0
+ */
+@GroovyASTTransformation(phase = CompilePhase.CANONICALIZATION)
+@CompileStatic
+public class ThreadInterruptibleASTTransformation extends AbstractInterruptibleASTTransformation {
+
+    private static final ClassNode MY_TYPE = ClassHelper.make(ThreadInterrupt)
+    private static final ClassNode THREAD_TYPE = ClassHelper.make(Thread)
+    private static final MethodNode CURRENTTHREAD_METHOD
+    private static final MethodNode ISINTERRUPTED_METHOD
+
+    static {
+        CURRENTTHREAD_METHOD = THREAD_TYPE.getMethod('currentThread', Parameter.EMPTY_ARRAY)
+        ISINTERRUPTED_METHOD = THREAD_TYPE.getMethod('isInterrupted', Parameter.EMPTY_ARRAY)
+    }
+
+    protected ClassNode type() {
+        return MY_TYPE;
+    }
+
+    protected String getErrorMessage() {
+        'Execution interrupted. The current thread has been interrupted.'
+    }
+
+    protected Expression createCondition() {
+        def currentThread = new MethodCallExpression(new ClassExpression(THREAD_TYPE),
+                'currentThread',
+                ArgumentListExpression.EMPTY_ARGUMENTS)
+        currentThread.methodTarget = CURRENTTHREAD_METHOD
+        def isInterrupted = new MethodCallExpression(
+                currentThread,
+                'isInterrupted', ArgumentListExpression.EMPTY_ARGUMENTS)
+        isInterrupted.methodTarget = ISINTERRUPTED_METHOD
+        [currentThread, isInterrupted]*.implicitThis = false
+
+        isInterrupted
+    }
+
+
+    @Override
+    public void visitClosureExpression(ClosureExpression closureExpr) {
+        def code = closureExpr.code
+        closureExpr.code = wrapBlock(code)
+        super.visitClosureExpression closureExpr
+    }
+
+    @Override
+    public void visitMethod(MethodNode node) {
+        if (checkOnMethodStart && !node.isSynthetic() && !node.isAbstract()) {
+            def code = node.code
+            node.code = wrapBlock(code);
+        }
+        super.visitMethod(node)
+    }
+}