You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by pa...@apache.org on 2017/12/19 10:25:19 UTC

[1/2] groovy git commit: update checkstyle for latest build

Repository: groovy
Updated Branches:
  refs/heads/GROOVY_2_5_X dafabb2eb -> 13522f887


http://git-wip-us.apache.org/repos/asf/groovy/blob/13522f88/pr617.patch
----------------------------------------------------------------------
diff --git a/pr617.patch b/pr617.patch
new file mode 100644
index 0000000..23f72a7
--- /dev/null
+++ b/pr617.patch
@@ -0,0 +1,293 @@
+From 2e36707b9446f8b48a85bee26f6ec746d56e8b95 Mon Sep 17 00:00:00 2001
+From: aalmiray <aa...@gmail.com>
+Date: Wed, 11 Oct 2017 16:34:27 +0200
+Subject: [PATCH 1/2] GROOVY-8352: add a @Generated annotation
+
+---
+ src/main/groovy/transform/Generated.java           | 36 ++++++++++
+ .../org/codehaus/groovy/classgen/Verifier.java     | 22 +++---
+ .../groovy/tools/javac/JavaStubGenerator.java      | 10 +--
+ .../groovy/transform/GeneratedTransformTest.groovy | 81 ++++++++++++++++++++++
+ 4 files changed, 136 insertions(+), 13 deletions(-)
+ create mode 100644 src/main/groovy/transform/Generated.java
+ create mode 100644 src/test/org/codehaus/groovy/transform/GeneratedTransformTest.groovy
+
+diff --git a/src/main/groovy/transform/Generated.java b/src/main/groovy/transform/Generated.java
+new file mode 100644
+index 0000000000..f7ea40af6d
+--- /dev/null
++++ b/src/main/groovy/transform/Generated.java
+@@ -0,0 +1,36 @@
++/*
++ *  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 Generated annotation is used to mark members that have been generated.
++ *
++ * @author Andres Almiray
++ * @author Jochen Theodorou
++ * @author Mark Hoffmann
++ */
++@Target({ElementType.METHOD, ElementType.CONSTRUCTOR, ElementType.TYPE, ElementType.FIELD})
++@Retention(RetentionPolicy.RUNTIME)
++public @interface Generated {
++}
+diff --git a/src/main/org/codehaus/groovy/classgen/Verifier.java b/src/main/org/codehaus/groovy/classgen/Verifier.java
+index b98e784577..f1251d7e7a 100644
+--- a/src/main/org/codehaus/groovy/classgen/Verifier.java
++++ b/src/main/org/codehaus/groovy/classgen/Verifier.java
+@@ -21,6 +21,7 @@
+ import groovy.lang.GroovyClassLoader;
+ import groovy.lang.GroovyObject;
+ import groovy.lang.MetaClass;
++import groovy.transform.Generated;
+ import org.codehaus.groovy.GroovyBugError;
+ import org.codehaus.groovy.ast.*;
+ import org.codehaus.groovy.ast.expr.ArgumentListExpression;
+@@ -124,6 +125,8 @@
+             new Parameter(ClassHelper.METACLASS_TYPE, "mc")
+     };
+ 
++    private static final Class GENERATED_ANNOTATION = Generated.class;
++
+     private ClassNode classNode;
+     private MethodNode methodNode;
+ 
+@@ -384,6 +387,7 @@ public void visit(MethodVisitor mv) {
+     protected void addGroovyObjectInterfaceAndMethods(ClassNode node, final String classInternalName) {
+         if (!node.isDerivedFromGroovyObject()) node.addInterface(ClassHelper.make(GroovyObject.class));
+         FieldNode metaClassField = getMetaClassField(node);
++        AnnotationNode generatedAnnotation = new AnnotationNode(ClassHelper.make(GENERATED_ANNOTATION));
+ 
+         if (!node.hasMethod("getMetaClass", Parameter.EMPTY_ARRAY)) {
+             metaClassField = setMetaClassFieldIfNotExists(node, metaClassField);
+@@ -425,7 +429,7 @@ public void visit(MethodVisitor mv) {
+                             mv.visitInsn(ARETURN);
+                         }
+                     })
+-            );
++            ).addAnnotation(generatedAnnotation);
+         }
+ 
+         Parameter[] parameters = new Parameter[]{new Parameter(ClassHelper.METACLASS_TYPE, "mc")};
+@@ -459,7 +463,7 @@ public void visit(MethodVisitor mv) {
+                     ACC_PUBLIC, ClassHelper.VOID_TYPE,
+                     SET_METACLASS_PARAMS, ClassNode.EMPTY_ARRAY,
+                     setMetaClassCode
+-            );
++            ).addAnnotation(generatedAnnotation);
+         }
+ 
+         if (!node.hasMethod("invokeMethod", INVOKE_METHOD_PARAMS)) {
+@@ -485,7 +489,7 @@ public void visit(MethodVisitor mv) {
+                             mv.visitInsn(ARETURN);
+                         }
+                     })
+-            );
++            ).addAnnotation(generatedAnnotation);
+         }
+ 
+         if (!node.hasMethod("getProperty", GET_PROPERTY_PARAMS)) {
+@@ -505,7 +509,7 @@ public void visit(MethodVisitor mv) {
+                             mv.visitInsn(ARETURN);
+                         }
+                     })
+-            );
++            ).addAnnotation(generatedAnnotation);
+         }
+ 
+         if (!node.hasMethod("setProperty", SET_PROPERTY_PARAMS)) {
+@@ -526,7 +530,7 @@ public void visit(MethodVisitor mv) {
+                             mv.visitInsn(RETURN);
+                         }
+                     })
+-            );
++            ).addAnnotation(generatedAnnotation);
+         }
+     }
+ 
+@@ -535,12 +539,12 @@ public void visit(MethodVisitor mv) {
+      * call will either be made to ClassNode.addSyntheticMethod() or ClassNode.addMethod(). If a non-synthetic method
+      * is to be added the ACC_SYNTHETIC modifier is removed if it has been accidentally supplied.
+      */
+-    protected void addMethod(ClassNode node, boolean shouldBeSynthetic, String name, int modifiers, ClassNode returnType, Parameter[] parameters,
+-                             ClassNode[] exceptions, Statement code) {
++    protected MethodNode addMethod(ClassNode node, boolean shouldBeSynthetic, String name, int modifiers, ClassNode returnType, Parameter[] parameters,
++                                   ClassNode[] exceptions, Statement code) {
+         if (shouldBeSynthetic) {
+-            node.addSyntheticMethod(name, modifiers, returnType, parameters, exceptions, code);
++            return node.addSyntheticMethod(name, modifiers, returnType, parameters, exceptions, code);
+         } else {
+-            node.addMethod(name, modifiers & ~ACC_SYNTHETIC, returnType, parameters, exceptions, code);
++            return node.addMethod(name, modifiers & ~ACC_SYNTHETIC, returnType, parameters, exceptions, code);
+         }
+     }
+ 
+diff --git a/src/main/org/codehaus/groovy/tools/javac/JavaStubGenerator.java b/src/main/org/codehaus/groovy/tools/javac/JavaStubGenerator.java
+index b672793c18..89d45aeba2 100644
+--- a/src/main/org/codehaus/groovy/tools/javac/JavaStubGenerator.java
++++ b/src/main/org/codehaus/groovy/tools/javac/JavaStubGenerator.java
+@@ -155,8 +155,8 @@ protected void addPropertyMethod(MethodNode method) {
+                     doAddMethod(method);
+                 }
+                 protected void addReturnIfNeeded(MethodNode node) {}
+-                protected void addMethod(ClassNode node, boolean shouldBeSynthetic, String name, int modifiers, ClassNode returnType, Parameter[] parameters, ClassNode[] exceptions, Statement code) {
+-                    doAddMethod(new MethodNode(name, modifiers, returnType, parameters, exceptions, code));
++                protected MethodNode addMethod(ClassNode node, boolean shouldBeSynthetic, String name, int modifiers, ClassNode returnType, Parameter[] parameters, ClassNode[] exceptions, Statement code) {
++                    return doAddMethod(new MethodNode(name, modifiers, returnType, parameters, exceptions, code));
+                 }
+ 
+                 protected void addConstructor(Parameter[] newParams, ConstructorNode ctor, Statement code, ClassNode node) {
+@@ -184,13 +184,15 @@ protected void addDefaultParameters(DefaultArgsAction action, MethodNode method)
+                     }
+                 }
+ 
+-                private void doAddMethod(MethodNode method) {
++                private MethodNode doAddMethod(MethodNode method) {
+                     String sig = method.getTypeDescriptor();
+ 
+-                    if (propertyMethodsWithSigs.containsKey(sig)) return;
++                    if (propertyMethodsWithSigs.containsKey(sig)) return method;
+ 
+                     propertyMethods.add(method);
+                     propertyMethodsWithSigs.put(sig, method);
++
++                    return method;
+                 }
+ 
+                 @Override
+diff --git a/src/test/org/codehaus/groovy/transform/GeneratedTransformTest.groovy b/src/test/org/codehaus/groovy/transform/GeneratedTransformTest.groovy
+new file mode 100644
+index 0000000000..34e9f0ea0c
+--- /dev/null
++++ b/src/test/org/codehaus/groovy/transform/GeneratedTransformTest.groovy
+@@ -0,0 +1,81 @@
++/*
++ *  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 org.junit.After
++import org.junit.Before
++import org.junit.Rule
++import org.junit.Test
++import org.junit.rules.TestName
++import org.junit.runner.RunWith
++import org.junit.runners.JUnit4
++
++import static org.junit.Assume.assumeTrue
++
++/**
++ * Tests for the @Generated annotation.
++ */
++@RunWith(JUnit4)
++class GeneratedTransformTest extends GroovyShellTestCase {
++    @Rule public TestName nameRule = new TestName()
++
++    @Before
++    void setUp() {
++        super.setUp()
++        // check java version requirements
++        def v = System.getProperty("java.specification.version")
++        assert v
++        assumeTrue('Test requires jre8+', nameRule.methodName.endsWith('_vm8').implies(new BigDecimal(v) >= 1.8))
++    }
++
++    @After
++    void tearDown() {
++        super.tearDown()
++    }
++
++    @Test
++    void testDefaultGroovyMethodsAreAnnotatedWithGenerated() {
++        def person = evaluate('''
++            class Person {
++                String name
++            }
++            new Person()
++        ''')
++
++        GroovyObject.declaredMethods.each { m ->
++            def method = person.class.declaredMethods.find { it.name == m.name }
++            assert method.annotations*.annotationType().name == ['groovy.transform.Generated']
++        }
++    }
++
++    @Test
++    void testOverridenDefaultGroovyMethodsAreNotAnnotatedWithGenerated() {
++        def person = evaluate('''
++            class Person {
++                String name
++                
++                def invokeMethod(String name, args) { }
++            }
++            new Person()
++        ''')
++
++        def method = person.class.declaredMethods.find { it.name == 'invokeMethod' }
++        assert !('groovy.transform.Generated' in method.annotations*.annotationType().name)
++    }
++}
+\ No newline at end of file
+
+From d2097c8cb1dc6080dc491d5fbae6b0732d697c23 Mon Sep 17 00:00:00 2001
+From: aalmiray <aa...@gmail.com>
+Date: Thu, 12 Oct 2017 10:07:07 +0200
+Subject: [PATCH 2/2] Remove author tags from javadoc
+
+---
+ src/main/groovy/transform/Generated.java | 4 ----
+ 1 file changed, 4 deletions(-)
+
+diff --git a/src/main/groovy/transform/Generated.java b/src/main/groovy/transform/Generated.java
+index f7ea40af6d..98eaf5b0df 100644
+--- a/src/main/groovy/transform/Generated.java
++++ b/src/main/groovy/transform/Generated.java
+@@ -25,10 +25,6 @@
+ 
+ /**
+  * The Generated annotation is used to mark members that have been generated.
+- *
+- * @author Andres Almiray
+- * @author Jochen Theodorou
+- * @author Mark Hoffmann
+  */
+ @Target({ElementType.METHOD, ElementType.CONSTRUCTOR, ElementType.TYPE, ElementType.FIELD})
+ @Retention(RetentionPolicy.RUNTIME)

http://git-wip-us.apache.org/repos/asf/groovy/blob/13522f88/pr622.patch
----------------------------------------------------------------------
diff --git a/pr622.patch b/pr622.patch
new file mode 100644
index 0000000..1d3df05
--- /dev/null
+++ b/pr622.patch
@@ -0,0 +1,237 @@
+From 3839297520e325b8520d856bd2d74fc5ee63cced Mon Sep 17 00:00:00 2001
+From: paulk <pa...@asert.com.au>
+Date: Mon, 30 Oct 2017 08:47:28 +1000
+Subject: [PATCH] GROOVY-8112: NPE in Groovy compiler when referencing @Field
+ in aic
+
+---
+ .../groovy/transform/FieldASTTransformation.java   | 104 +++++++++++++++++----
+ .../groovy/transform/FieldTransformTest.groovy     |  39 +++++++-
+ 2 files changed, 122 insertions(+), 21 deletions(-)
+
+diff --git a/src/main/org/codehaus/groovy/transform/FieldASTTransformation.java b/src/main/org/codehaus/groovy/transform/FieldASTTransformation.java
+index 52b4406b94..8e6b58e8b5 100644
+--- a/src/main/org/codehaus/groovy/transform/FieldASTTransformation.java
++++ b/src/main/org/codehaus/groovy/transform/FieldASTTransformation.java
+@@ -27,15 +27,19 @@
+ import org.codehaus.groovy.ast.ClassCodeExpressionTransformer;
+ import org.codehaus.groovy.ast.ClassHelper;
+ import org.codehaus.groovy.ast.ClassNode;
++import org.codehaus.groovy.ast.ConstructorNode;
+ import org.codehaus.groovy.ast.FieldNode;
+ import org.codehaus.groovy.ast.MethodNode;
++import org.codehaus.groovy.ast.Parameter;
+ import org.codehaus.groovy.ast.Variable;
+ import org.codehaus.groovy.ast.VariableScope;
+-import org.codehaus.groovy.ast.expr.BinaryExpression;
++import org.codehaus.groovy.ast.expr.ArgumentListExpression;
+ import org.codehaus.groovy.ast.expr.ClosureExpression;
+ import org.codehaus.groovy.ast.expr.ConstantExpression;
++import org.codehaus.groovy.ast.expr.ConstructorCallExpression;
+ import org.codehaus.groovy.ast.expr.DeclarationExpression;
+ import org.codehaus.groovy.ast.expr.Expression;
++import org.codehaus.groovy.ast.expr.TupleExpression;
+ import org.codehaus.groovy.ast.expr.VariableExpression;
+ import org.codehaus.groovy.ast.stmt.ExpressionStatement;
+ import org.codehaus.groovy.classgen.VariableScopeVisitor;
+@@ -44,6 +48,7 @@
+ import org.codehaus.groovy.runtime.MetaClassHelper;
+ import org.objectweb.asm.Opcodes;
+ 
++import java.util.ArrayList;
+ import java.util.Arrays;
+ import java.util.Iterator;
+ import java.util.List;
+@@ -59,9 +64,6 @@
+ 
+ /**
+  * Handles transformation for the @Field annotation.
+- *
+- * @author Paul King
+- * @author Cedric Champeau
+  */
+ @GroovyASTTransformation(phase = CompilePhase.SEMANTIC_ANALYSIS)
+ public class FieldASTTransformation extends ClassCodeExpressionTransformer implements ASTTransformation, Opcodes {
+@@ -77,6 +79,7 @@
+     private String variableName;
+     private FieldNode fieldNode;
+     private ClosureExpression currentClosure;
++    private ConstructorCallExpression currentAIC;
+ 
+     public void visit(ASTNode[] nodes, SourceUnit source) {
+         sourceUnit = source;
+@@ -166,23 +169,76 @@ public Expression transform(Expression expr) {
+         } else if (insideScriptBody && expr instanceof VariableExpression && currentClosure != null) {
+             VariableExpression ve = (VariableExpression) expr;
+             if (ve.getName().equals(variableName)) {
+-                // we may only check the variable name because the Groovy compiler
+-                // already fails if a variable with the same name already exists in the scope.
+-                // this means that a closure cannot shadow a class variable
+-                ve.setAccessedVariable(fieldNode);
+-                final VariableScope variableScope = currentClosure.getVariableScope();
+-                final Iterator<Variable> iterator = variableScope.getReferencedLocalVariablesIterator();
+-                while (iterator.hasNext()) {
+-                    Variable next = iterator.next();
+-                    if (next.getName().equals(variableName)) iterator.remove();
+-                }
+-                variableScope.putReferencedClassVariable(fieldNode);
++                adjustToClassVar(ve);
+                 return ve;
+             }
++        } else if (currentAIC != null && expr instanceof ArgumentListExpression) {
++            // if a match is found, the compiler will have already set up aic constructor to hav
++            // an argument which isn't needed since we'll be accessing the field; we must undo it
++            Expression skip = null;
++            List<Expression> origArgList = ((ArgumentListExpression) expr).getExpressions();
++            for (int i = 0; i < origArgList.size(); i++) {
++                Expression arg = origArgList.get(i);
++                if (matchesCandidate(arg)) {
++                    skip = arg;
++                    adjustConstructorAndFields(i, currentAIC.getType());
++                    break;
++                }
++            }
++            if (skip != null) {
++                return adjustedArgList(skip, origArgList);
++            }
+         }
+         return expr.transformExpression(this);
+     }
+ 
++    private boolean matchesCandidate(Expression arg) {
++        return arg instanceof VariableExpression && ((VariableExpression) arg).getAccessedVariable() == candidate.getVariableExpression().getAccessedVariable();
++    }
++
++    private Expression adjustedArgList(Expression skip, List<Expression> origArgs) {
++        List<Expression> newArgs = new ArrayList<Expression>(origArgs.size() - 1);
++        for (Expression origArg : origArgs) {
++            if (skip != origArg) {
++                newArgs.add(origArg);
++            }
++        }
++        return new ArgumentListExpression(newArgs);
++    }
++
++    private void adjustConstructorAndFields(int skipIndex, ClassNode type) {
++        List<ConstructorNode> constructors = type.getDeclaredConstructors();
++        if (constructors.size() == 1) {
++            ConstructorNode constructor = constructors.get(0);
++            Parameter[] params = constructor.getParameters();
++            Parameter[] newParams = new Parameter[params.length - 1];
++            int to = 0;
++            for (int from = 0; from < params.length; from++) {
++                if (from != skipIndex) {
++                    newParams[to++] = params[from];
++                }
++            }
++            type.removeConstructor(constructor);
++            // code doesn't mention the removed param at this point, okay to leave as is
++            type.addConstructor(constructor.getModifiers(), newParams, constructor.getExceptions(), constructor.getCode());
++            type.removeField(variableName);
++        }
++    }
++
++    private void adjustToClassVar(VariableExpression expr) {
++        // we only need to check the variable name because the Groovy compiler
++        // already fails if a variable with the same name already exists in the scope.
++        // this means that a closure cannot shadow a class variable
++        expr.setAccessedVariable(fieldNode);
++        final VariableScope variableScope = currentClosure.getVariableScope();
++        final Iterator<Variable> iterator = variableScope.getReferencedLocalVariablesIterator();
++        while (iterator.hasNext()) {
++            Variable next = iterator.next();
++            if (next.getName().equals(variableName)) iterator.remove();
++        }
++        variableScope.putReferencedClassVariable(fieldNode);
++    }
++
+     @Override
+     public void visitClosureExpression(final ClosureExpression expression) {
+         ClosureExpression old = currentClosure;
+@@ -192,6 +248,20 @@ public void visitClosureExpression(final ClosureExpression expression) {
+     }
+ 
+     @Override
++    public void visitConstructorCallExpression(final ConstructorCallExpression cce) {
++        if (!insideScriptBody || !cce.isUsingAnonymousInnerClass()) return;
++        ConstructorCallExpression old = currentAIC;
++        currentAIC = cce;
++        Expression newArgs = transform(cce.getArguments());
++        if (cce.getArguments() instanceof TupleExpression && newArgs instanceof TupleExpression) {
++            List<Expression> argList = ((TupleExpression) cce.getArguments()).getExpressions();
++            argList.clear();
++            argList.addAll(((TupleExpression) newArgs).getExpressions());
++        }
++        currentAIC = old;
++    }
++
++    @Override
+     public void visitMethod(MethodNode node) {
+         Boolean oldInsideScriptBody = insideScriptBody;
+         if (node.isScriptBody()) insideScriptBody = true;
+@@ -202,9 +272,7 @@ public void visitMethod(MethodNode node) {
+     @Override
+     public void visitExpressionStatement(ExpressionStatement es) {
+         Expression exp = es.getExpression();
+-        if (exp instanceof BinaryExpression) {
+-            exp.visit(this);
+-        }
++        exp.visit(this);
+         super.visitExpressionStatement(es);
+     }
+ 
+diff --git a/src/test/org/codehaus/groovy/transform/FieldTransformTest.groovy b/src/test/org/codehaus/groovy/transform/FieldTransformTest.groovy
+index 2821f6e11c..6575720bfb 100644
+--- a/src/test/org/codehaus/groovy/transform/FieldTransformTest.groovy
++++ b/src/test/org/codehaus/groovy/transform/FieldTransformTest.groovy
+@@ -21,8 +21,7 @@ package org.codehaus.groovy.transform
+ import gls.CompilableTestSupport
+ 
+ /**
+- * @author Paul King
+- * @author C�dric Champeau
++ * Tests for the {@code @Field} transformation
+  */
+ class FieldTransformTest extends CompilableTestSupport {
+ 
+@@ -226,4 +225,38 @@ class FieldTransformTest extends CompilableTestSupport {
+             assert foo + bar + baz == 'foobarbaz'
+         '''
+     }
+-}
+\ No newline at end of file
++
++    void testAnonymousInnerClassReferencesToField() {
++        // GROOVY-8112
++        assertScript '''
++            @groovy.transform.Field
++            StringBuilder logger = new StringBuilder()
++            logger.append('a')
++            ['b'].each {
++                logger.append(it)
++                new Object() {
++                    String toString() {
++                        logger.append('c')
++                        ['d'].each { logger.append(it) }
++                    }
++                }.toString()
++            }
++            Closure c = { logger.append('e') }
++            c()
++            // control: worked previously, make sure we didn't break
++            def method() {
++                logger.append('f')
++                ['g'].each {
++                    logger.append(it)
++                    new Object() {
++                        String toString() {
++                            logger.append('h')
++                        }
++                    }.toString()
++                }
++            }
++            method()
++            assert logger.toString() == 'abcdefgh'
++        '''
++    }
++}

http://git-wip-us.apache.org/repos/asf/groovy/blob/13522f88/pr625.patch
----------------------------------------------------------------------
diff --git a/pr625.patch b/pr625.patch
new file mode 100644
index 0000000..4d0e8d2
--- /dev/null
+++ b/pr625.patch
@@ -0,0 +1,65 @@
+From 03fd268d814c491f1424f9fe8d8a0d30c5c333a5 Mon Sep 17 00:00:00 2001
+From: Shil Sinha <sh...@gmail.com>
+Date: Tue, 31 Oct 2017 13:29:19 -0400
+Subject: [PATCH] GROOVY-8369: Statically compiled property access on enum
+ class throws NoSuchFieldError
+
+---
+ .../classgen/asm/sc/StaticTypesCallSiteWriter.java      | 10 +++++-----
+ .../asm/sc/FieldsAndPropertiesStaticCompileTest.groovy  | 17 +++++++++++++++++
+ 2 files changed, 22 insertions(+), 5 deletions(-)
+
+diff --git a/src/main/org/codehaus/groovy/classgen/asm/sc/StaticTypesCallSiteWriter.java b/src/main/org/codehaus/groovy/classgen/asm/sc/StaticTypesCallSiteWriter.java
+index 8d003ebc75..2eaa9348e6 100644
+--- a/src/main/org/codehaus/groovy/classgen/asm/sc/StaticTypesCallSiteWriter.java
++++ b/src/main/org/codehaus/groovy/classgen/asm/sc/StaticTypesCallSiteWriter.java
+@@ -148,11 +148,6 @@ public void makeGetPropertySite(Expression receiver, final String methodName, fi
+         }
+         if (makeGetPropertyWithGetter(receiver, receiverType, methodName, safe, implicitThis)) return;
+         if (makeGetField(receiver, receiverType, methodName, safe, implicitThis, samePackages(receiverType.getPackageName(), classNode.getPackageName()))) return;
+-        if (receiverType.isEnum()) {
+-            mv.visitFieldInsn(GETSTATIC, BytecodeHelper.getClassInternalName(receiverType), methodName, BytecodeHelper.getTypeDescription(receiverType));
+-            controller.getOperandStack().push(receiverType);
+-            return;
+-        }
+         if (receiver instanceof ClassExpression) {
+             if (makeGetField(receiver, receiver.getType(), methodName, safe, implicitThis, samePackages(receiver.getType().getPackageName(), classNode.getPackageName()))) return;
+             if (makeGetPropertyWithGetter(receiver, receiver.getType(), methodName, safe, implicitThis)) return;
+@@ -163,6 +158,11 @@ public void makeGetPropertySite(Expression receiver, final String methodName, fi
+             if (makeGetPropertyWithGetter(receiver, CLASS_Type, methodName, safe, implicitThis)) return;
+             if (makeGetField(receiver, CLASS_Type, methodName, safe, false, true)) return;
+         }
++        if (receiverType.isEnum()) {
++            mv.visitFieldInsn(GETSTATIC, BytecodeHelper.getClassInternalName(receiverType), methodName, BytecodeHelper.getTypeDescription(receiverType));
++            controller.getOperandStack().push(receiverType);
++            return;
++        }
+         if (makeGetPrivateFieldWithBridgeMethod(receiver, receiverType, methodName, safe, implicitThis)) return;
+ 
+         // GROOVY-5580, it is still possible that we're calling a superinterface property
+diff --git a/src/test/org/codehaus/groovy/classgen/asm/sc/FieldsAndPropertiesStaticCompileTest.groovy b/src/test/org/codehaus/groovy/classgen/asm/sc/FieldsAndPropertiesStaticCompileTest.groovy
+index 6af5f135f1..2bf0a867bd 100644
+--- a/src/test/org/codehaus/groovy/classgen/asm/sc/FieldsAndPropertiesStaticCompileTest.groovy
++++ b/src/test/org/codehaus/groovy/classgen/asm/sc/FieldsAndPropertiesStaticCompileTest.groovy
+@@ -696,4 +696,21 @@ import org.codehaus.groovy.transform.sc.ListOfExpressionsExpression
+             assert astTrees['A$_closure1'][1].contains('INVOKESTATIC A.pfaccess$02 (LA;Ljava/lang/String;)Ljava/lang/String;')
+         }
+     }
++
++    //GROOVY-8369
++    void testPropertyAccessOnEnumClass() {
++        try {
++            assertScript '''
++                enum Foo {}
++
++                def test() {
++                    println Foo.getModifiers() // => 16401 // ENUM | FINAL | PUBLIC (see GROOVY_8360 wrt STATIC)
++                    println Foo.modifiers      // java.lang.NoSuchFieldError: modifiers
++                }    
++                test()
++            '''
++        } finally {
++            //println astTrees
++        }
++    }
+ }

http://git-wip-us.apache.org/repos/asf/groovy/blob/13522f88/src/main/groovy/transform/MapArguments.java.bak
----------------------------------------------------------------------
diff --git a/src/main/groovy/transform/MapArguments.java.bak b/src/main/groovy/transform/MapArguments.java.bak
new file mode 100644
index 0000000..c4d097d
--- /dev/null
+++ b/src/main/groovy/transform/MapArguments.java.bak
@@ -0,0 +1,33 @@
+/*
+ *  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.transform.GroovyASTTransformationClass;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.METHOD})
+@GroovyASTTransformationClass("org.apache.groovy.transform.MapArgumentsASTTransformation")
+public @interface MapArguments {
+    Class typeHint() default Object.class;
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/13522f88/src/main/org/apache/groovy/transform/MapArgumentsASTTransformation.java.bak
----------------------------------------------------------------------
diff --git a/src/main/org/apache/groovy/transform/MapArgumentsASTTransformation.java.bak b/src/main/org/apache/groovy/transform/MapArgumentsASTTransformation.java.bak
new file mode 100644
index 0000000..bd9b293
--- /dev/null
+++ b/src/main/org/apache/groovy/transform/MapArgumentsASTTransformation.java.bak
@@ -0,0 +1,165 @@
+/*
+ *  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.apache.groovy.transform;
+
+import groovy.transform.MapArguments;
+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.ConstructorNode;
+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.Expression;
+import org.codehaus.groovy.ast.expr.VariableExpression;
+import org.codehaus.groovy.control.CompilePhase;
+import org.codehaus.groovy.control.SourceUnit;
+import org.codehaus.groovy.transform.AbstractASTTransformation;
+import org.codehaus.groovy.transform.GroovyASTTransformation;
+import org.objectweb.asm.Opcodes;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static org.apache.groovy.ast.tools.FactoryUtils.args;
+import static org.apache.groovy.ast.tools.FactoryUtils.callThisX;
+import static org.apache.groovy.ast.tools.FactoryUtils.castX;
+import static org.apache.groovy.ast.tools.FactoryUtils.classX;
+import static org.apache.groovy.ast.tools.FactoryUtils.constX;
+import static org.apache.groovy.ast.tools.FactoryUtils.ctorX;
+import static org.apache.groovy.ast.tools.FactoryUtils.stmt;
+import static org.apache.groovy.ast.tools.FactoryUtils.varX;
+
+@GroovyASTTransformation(phase = CompilePhase.SEMANTIC_ANALYSIS)
+public class MapArgumentsASTTransformation extends AbstractASTTransformation {
+
+    @Override
+    public void visit(ASTNode[] nodes, SourceUnit source) {
+        init(nodes, source);
+
+        MethodNode methodNode = (MethodNode) nodes[1];
+
+        Parameter[] parameters = methodNode.getParameters();
+        Parameter closureParameter = null;
+
+        switch (parameters.length) {
+            case 0:
+                addError("MapArguments parameters should not be empty", methodNode);
+                return;
+            case 1:
+                //TODO more object checks
+                break;
+            case 2:
+                closureParameter = parameters[1];
+                if (!(closureParameter.getType().isDerivedFrom(ClassHelper.CLOSURE_TYPE)) && !ClassHelper.isSAMType(closureParameter.getType())) {
+                    addError("MapArguments second parameter can be a closure only", closureParameter);
+                    return;
+                }
+                break;
+            default:
+                addError("MapArguments parameters length should not be greater than 2", methodNode);
+                return;
+        }
+
+        Parameter mapParameter = new Parameter(nonGeneric(ClassHelper.MAP_TYPE), "__namedArgs");
+
+        Parameter[] mapBasedMethodParameters = closureParameter != null ? new Parameter[]{mapParameter, closureParameter} : new Parameter[]{mapParameter};
+
+        ClassNode declaringClass = methodNode.getDeclaringClass();
+
+        if (declaringClass.hasMethod(methodNode.getName(), mapBasedMethodParameters)) {
+            addError("This class already has a Map-based method", methodNode);
+            return;
+        }
+
+        Expression convertedValueExpression;
+
+        ClassNode parameterType = parameters[0].getType();
+        if (checkForMapConstructor(parameterType)) {
+            ArgumentListExpression convertedArguments = args(varX(mapParameter));
+            if ((parameterType.getModifiers() & Opcodes.ACC_STATIC) == 0) {
+                if(methodNode.isStatic()) {
+                    addError("You can't use inner class as map argument since it's impossible to instantiate it", methodNode);
+                    return;
+                }
+                convertedArguments.getExpressions().add(0, VariableExpression.THIS_EXPRESSION);
+            }
+            convertedValueExpression = ctorX(parameterType, convertedArguments);
+        } else {
+            convertedValueExpression = castX(parameterType, varX(mapParameter));
+        }
+
+        ArgumentListExpression oldMethodArguments = FactoryUtils.args(convertedValueExpression);
+
+        List<MethodNode> generatedMethods = new ArrayList<MethodNode>();
+        generatedMethods.add(declaringClass.addMethod(
+                methodNode.getName(),
+                methodNode.getModifiers(),
+                methodNode.getReturnType(),
+                mapBasedMethodParameters,
+                methodNode.getExceptions(),
+                stmt(callThisX(methodNode.getName(), oldMethodArguments))
+        ));
+
+        if (closureParameter != null) {
+            oldMethodArguments.addExpression(varX(closureParameter));
+            generatedMethods.add(declaringClass.addMethod(
+                    methodNode.getName(),
+                    methodNode.getModifiers(),
+                    methodNode.getReturnType(),
+                    new Parameter[]{mapBasedMethodParameters[0]},
+                    methodNode.getExceptions(),
+                    stmt(callThisX(
+                            methodNode.getName(),
+                            args(oldMethodArguments.getExpression(0), castX(closureParameter.getType(), constX(null)))
+                    ))
+            ));
+        }
+
+        for (MethodNode generatedMethod : generatedMethods) {
+            AnnotationNode mapArgumentsAnnotationNode = new AnnotationNode(ClassHelper.makeWithoutCaching(MapArguments.class));
+            mapArgumentsAnnotationNode.setMember("typeHint", classX(parameterType));
+            generatedMethod.addAnnotation(mapArgumentsAnnotationNode);
+        }
+    }
+
+    protected boolean checkForMapConstructor(ClassNode parameterType) {
+        List<ConstructorNode> declaredConstructors = parameterType.getDeclaredConstructors();
+
+        for (ConstructorNode declaredConstructor : declaredConstructors) {
+            Parameter[] declaredConstructorParameters = declaredConstructor.getParameters();
+            if (declaredConstructorParameters.length != 1) {
+                continue;
+            }
+
+            ClassNode declaredConstructorParameterType = declaredConstructorParameters[0].getType();
+
+            if (declaredConstructorParameterType == null) {
+                continue;
+            }
+
+            if (declaredConstructorParameterType.equals(ClassHelper.MAP_TYPE)) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/groovy/blob/13522f88/src/test/org/codehaus/groovy/tools/stubgenerator/Groovy8224Bug.groovy.bak
----------------------------------------------------------------------
diff --git a/src/test/org/codehaus/groovy/tools/stubgenerator/Groovy8224Bug.groovy.bak b/src/test/org/codehaus/groovy/tools/stubgenerator/Groovy8224Bug.groovy.bak
new file mode 100644
index 0000000..8fe711b
--- /dev/null
+++ b/src/test/org/codehaus/groovy/tools/stubgenerator/Groovy8224Bug.groovy.bak
@@ -0,0 +1,53 @@
+/*
+ *  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.tools.stubgenerator
+
+/**
+ * Test that traits include getters/setters.
+ */
+class Groovy8224Bug extends StringSourcesStubTestCase {
+
+    Map<String, String> provideSources() {
+        [
+                'Foo.groovy': '''
+                    trait GroovyXTrait {
+                        int foo
+                    }
+                ''',
+                'Main.java': '''
+                    class Main {
+                        public static void main(String[] args) {
+                            new GroovyXImpl().getFoo();
+                        }
+                    }
+                ''',
+                'GroovyXImpl.groovy': '''
+                    class GroovyXImpl implements GroovyXTrait { }
+                ''',
+        ]
+    }
+
+    void verifyStubs() {
+        def stubSource = stubJavaSourceFor('GroovyXImpl')
+        assert stubSource.contains('interface Foo')
+        assert stubSource.contains('int foo()')
+        assert stubSource.contains('void baz(int y)')
+        assert stubSource.contains('void bar(int x)')
+    }
+}


[2/2] groovy git commit: update checkstyle for latest build

Posted by pa...@apache.org.
update checkstyle for latest build

one of the rules we previously used is no longer included


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

Branch: refs/heads/GROOVY_2_5_X
Commit: 13522f8871d768e1d65c522325bbc47a88d77a2e
Parents: dafabb2
Author: paulk <pa...@asert.com.au>
Authored: Tue Dec 19 20:25:08 2017 +1000
Committer: paulk <pa...@asert.com.au>
Committed: Tue Dec 19 20:25:08 2017 +1000

----------------------------------------------------------------------
 Groovy7037.patch                                |  71 ++++
 Groovy8295.patch                                |  61 +++
 config/checkstyle/checkstyle.xml                |   3 +-
 groovy8260Extras.patch                          | 388 +++++++++++++++++++
 groovy8260c.patch                               | 188 +++++++++
 ivy_snapshot.patch                              |  24 ++
 pr502.patch                                     | 118 ++++++
 pr507.patch                                     |  25 ++
 pr555.patch                                     | 312 +++++++++++++++
 pr555a.patch                                    |  94 +++++
 pr565.patch                                     | 168 ++++++++
 pr584.patch                                     |  57 +++
 pr597.patch                                     |  26 ++
 pr603.patch                                     | 102 +++++
 pr607.patch                                     |  60 +++
 pr617.patch                                     | 293 ++++++++++++++
 pr622.patch                                     | 237 +++++++++++
 pr625.patch                                     |  65 ++++
 src/main/groovy/transform/MapArguments.java.bak |  33 ++
 .../MapArgumentsASTTransformation.java.bak      | 165 ++++++++
 .../stubgenerator/Groovy8224Bug.groovy.bak      |  53 +++
 21 files changed, 2542 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/groovy/blob/13522f88/Groovy7037.patch
----------------------------------------------------------------------
diff --git a/Groovy7037.patch b/Groovy7037.patch
new file mode 100644
index 0000000..2417534
--- /dev/null
+++ b/Groovy7037.patch
@@ -0,0 +1,71 @@
+Index: src/test/groovy/bugs/Groovy7037Bug.groovy
+IDEA additional info:
+Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
+<+>UTF-8
+===================================================================
+--- src/test/groovy/bugs/Groovy7037Bug.groovy	(revision )
++++ src/test/groovy/bugs/Groovy7037Bug.groovy	(revision )
+@@ -0,0 +1,40 @@
++/*
++ *  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.bugs
++
++class Groovy7037Bug extends GroovyTestCase {
++    void testGetAtShouldWorkWithVarArgs() {
++        assertScript '''
++            class Test {
++                def getAt(Integer x, Long y) { "A: $x $y" }
++                def getAt(Integer x, Long... y) { "B: $x ${y.join(' ')}" }
++            }
++
++            def t = new Test()
++            assert t[2, 4L] == 'A: 2 4'
++            def items = [2, 4L]
++            assert t[*items] == 'A: 2 4'
++            assert t.getAt(2, 4L) == 'A: 2 4'
++            assert t[2] == 'B: 2 '
++            assert t.getAt(2) == 'B: 2 '
++            assert t.getAt(2, 4L, 5L) == 'B: 2 4 5'
++            assert t[2, 4L, 5L] == 'B: 2 4 5'
++        '''
++    }
++}
+Index: src/main/org/codehaus/groovy/classgen/asm/BinaryExpressionHelper.java
+IDEA additional info:
+Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
+<+>UTF-8
+===================================================================
+--- src/main/org/codehaus/groovy/classgen/asm/BinaryExpressionHelper.java	(date 1472272655000)
++++ src/main/org/codehaus/groovy/classgen/asm/BinaryExpressionHelper.java	(revision )
+@@ -242,6 +242,15 @@
+             if (controller.getCompileStack().isLHS()) {
+                 evaluateEqual(expression, false);
+             } else {
++                Expression arguments = expression.getRightExpression();
++                if (arguments instanceof ListExpression) {
++                    Expression newArgs = new ArgumentListExpression(((ListExpression) arguments).getExpressions());
++                    newArgs.setSourcePosition(arguments);
++                    controller.getInvocationWriter().makeCall(
++                            expression, expression.getLeftExpression(), new ConstantExpression("getAt"),
++                            newArgs, InvocationWriter.invokeMethod, false, false, false);
++                    break;
++                }
+                 evaluateBinaryExpression("getAt", expression);
+             }
+             break;

http://git-wip-us.apache.org/repos/asf/groovy/blob/13522f88/Groovy8295.patch
----------------------------------------------------------------------
diff --git a/Groovy8295.patch b/Groovy8295.patch
new file mode 100644
index 0000000..4545691
--- /dev/null
+++ b/Groovy8295.patch
@@ -0,0 +1,61 @@
+--- C:\Users\U0076777\Groovyc-2.4.12.txt	2017-08-29 17:54:18.050000000 -0500
++++ C:\Users\U0076777\Groovyc-edited.txt	2017-08-29 17:55:43.727000000 -0500
+@@ -1006,7 +1006,7 @@
+             commandLineList.add(javaHome + separator + "bin" + separator + "java");
+         }
+         commandLineList.add("-classpath");
+-        commandLineList.add(classpath.toString());
++        commandLineList.add(classpath.toString().replace(getProject().getBaseDir().getAbsolutePath(), "."));
+ 
+         final String fileEncodingProp = System.getProperty("file.encoding");
+         if ((fileEncodingProp != null) && !fileEncodingProp.equals("")) {
+@@ -1036,7 +1036,7 @@
+ 
+     private void doNormalCommandLineList(List<String> commandLineList, List<String> jointOptions, Path classpath) {
+         commandLineList.add("--classpath");
+-        commandLineList.add(classpath.toString());
++        commandLineList.add(classpath.toString().replace(getProject().getBaseDir().getAbsolutePath(), "."));
+         if (jointCompilation) {
+             commandLineList.add("-j");
+             commandLineList.addAll(jointOptions);
+@@ -1100,18 +1100,12 @@
+     }
+ 
+     private String[] makeCommandLine(List<String> commandLineList) {
+-        final String[] commandLine = new String[commandLineList.size()];
+-        for (int i = 0; i < commandLine.length; ++i) {
+-            commandLine[i] = commandLineList.get(i);
+-        }
+-        log.verbose("Compilation arguments:");
+-        log.verbose(DefaultGroovyMethods.join(commandLine, "\n"));
+-        return commandLine;
++        log.verbose("Compilation arguments:\n" + DefaultGroovyMethods.join(commandLineList, "\n"));
++        return commandLineList.toArray(new String[commandLineList.size()]);
+     }
+ 
+     private void runForked(String[] commandLine) {
+-        // use the main method in FileSystemCompiler
+-        final Execute executor = new Execute(); // new LogStreamHandler ( attributes , Project.MSG_INFO , Project.MSG_WARN ) ) ;
++        final Execute executor = new Execute();
+         executor.setAntRun(getProject());
+         executor.setWorkingDirectory(getProject().getBaseDir());
+         executor.setCommandline(commandLine);
+@@ -1280,12 +1274,12 @@
+                  * may not exist in the classpath yet
+                  */
+                 if (!found && new File(cpEntry).exists()) {
+-                	try {
+-                		antLoader.addPathElement(cpEntry);
+-                	}
+-                	catch(BuildException e) {
+-                		log.warn("The classpath entry " + cpEntry + " is not a valid Java resource");
+-                	}
++                    try {
++                        antLoader.addPathElement(cpEntry);
++                    }
++                    catch(BuildException e) {
++                        log.warn("The classpath entry " + cpEntry + " is not a valid Java resource");
++                    }
+                 }
+             }
+         }

http://git-wip-us.apache.org/repos/asf/groovy/blob/13522f88/config/checkstyle/checkstyle.xml
----------------------------------------------------------------------
diff --git a/config/checkstyle/checkstyle.xml b/config/checkstyle/checkstyle.xml
index 34aebe1..339228e 100644
--- a/config/checkstyle/checkstyle.xml
+++ b/config/checkstyle/checkstyle.xml
@@ -154,7 +154,8 @@
         <module name="UpperEll"/>
         <!-- off for now - to allow parentheses which add clarity -->
         <!--<module name="UnnecessaryParentheses"/>-->
-        <module name="JUnitTestCase"/>
+        <!-- removed in recent versions of checkstyle -->
+        <!--<module name="JUnitTestCase"/>-->
         <module name="FinalClass"/>
         <!-- good to have but pollutes coverage -->
         <!--<module name="HideUtilityClassConstructor"/>-->

http://git-wip-us.apache.org/repos/asf/groovy/blob/13522f88/groovy8260Extras.patch
----------------------------------------------------------------------
diff --git a/groovy8260Extras.patch b/groovy8260Extras.patch
new file mode 100644
index 0000000..24f20e6
--- /dev/null
+++ b/groovy8260Extras.patch
@@ -0,0 +1,388 @@
+Index: src/test/groovy/transform/stc/MiscSTCTest.groovy
+IDEA additional info:
+Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
+<+>UTF-8
+===================================================================
+--- src/test/groovy/transform/stc/MiscSTCTest.groovy	(revision 456aa4dd37dbcebcfb263db2914b2d84246bc30f)
++++ src/test/groovy/transform/stc/MiscSTCTest.groovy	(revision )
+@@ -275,5 +275,64 @@
+     public static class MiscSTCTestSupport {
+         static def foo() { '123' }
+     }
++
++    void testTernaryParam() {
++        assertScript '''
++            Date ternaryParam(Object input) {
++                input instanceof Date ? input : null
++            }
++            def d = new Date()
++            assert ternaryParam(42) == null
++            assert ternaryParam('foo') == null
++            assert ternaryParam(d) == d
++        '''
++    }
++
++    void testTernaryLocalVar() {
++        assertScript '''
++            Date ternaryLocalVar(Object input) {
++                Object copy = input
++                copy instanceof Date ? copy : null
++            }
++            def d = new Date()
++            assert ternaryLocalVar(42) == null
++            assert ternaryLocalVar('foo') == null
++            assert ternaryLocalVar(d) == d
++        '''
++    }
++
++    void testIfThenElseParam() {
++        assertScript '''
++            Date ifThenElseParam(Object input) {
++                if (input instanceof Date) {
++                    input
++                } else {
++                    null
++                }
++            }
++            def d = new Date()
++            assert ifThenElseParam(42) == null
++            assert ifThenElseParam('foo') == null
++            assert ifThenElseParam(d) == d
++        '''
++    }
++
++    void testIfThenElseLocalVar() {
++        assertScript '''
++            Date ifThenElseLocalVar(Object input) {
++                Date result
++                if (input instanceof Date) {
++                    result = input
++                } else {
++                    result = null
++                }
++                result
++            }
++            def d = new Date()
++            assert ifThenElseLocalVar(42) == null
++            assert ifThenElseLocalVar('foo') == null
++            assert ifThenElseLocalVar(d) == d
++        '''
++    }
+ }
+ 
+Index: src/main/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
+IDEA additional info:
+Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
+<+>UTF-8
+===================================================================
+--- src/main/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java	(revision 456aa4dd37dbcebcfb263db2914b2d84246bc30f)
++++ src/main/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java	(revision )
+@@ -112,7 +112,6 @@
+ import static org.codehaus.groovy.syntax.Types.COMPARE_EQUAL;
+ import static org.codehaus.groovy.syntax.Types.COMPARE_NOT_EQUAL;
+ import static org.codehaus.groovy.syntax.Types.COMPARE_NOT_IN;
+-import static org.codehaus.groovy.syntax.Types.COMPARE_NOT_INSTANCEOF;
+ import static org.codehaus.groovy.syntax.Types.COMPARE_TO;
+ import static org.codehaus.groovy.syntax.Types.DIVIDE;
+ import static org.codehaus.groovy.syntax.Types.DIVIDE_EQUAL;
+@@ -483,7 +482,20 @@
+             }
+         }
+ 
+-        if (! (vexp.getAccessedVariable() instanceof DynamicVariable)) return;
++        if (! (vexp.getAccessedVariable() instanceof DynamicVariable)) {
++            //if (vexp.getAccessedVariable() instanceof Parameter) {
++                ClassNode inferredTypeFromTempInfo = getInferredTypeFromTempInfo(vexp, null);
++                if (inferredTypeFromTempInfo != null) {
++                    storeType(vexp, inferredTypeFromTempInfo);
++                }
++//            } else if (vexp.getAccessedVariable() instanceof VariableExpression) {
++//                ClassNode inferredTypeFromTempInfo = getInferredTypeFromTempInfo((Expression) vexp.getAccessedVariable(), null);
++//                if (inferredTypeFromTempInfo != null) {
++//                    storeType((Expression) vexp.getAccessedVariable(), inferredTypeFromTempInfo);
++//                }
++//            }
++            return;
++        }
+ 
+         // a dynamic variable is either an undeclared variable
+         // or a member of a class used in a 'with'
+@@ -668,6 +680,9 @@
+                 if (typeCheckingContext.ifElseForWhileAssignmentTracker != null && leftExpression instanceof VariableExpression
+                         && !isNullConstant(rightExpression)) {
+                     Variable accessedVariable = ((VariableExpression) leftExpression).getAccessedVariable();
++                    if (accessedVariable instanceof Parameter) {
++                        accessedVariable = new ParameterVariableExpression((Parameter) accessedVariable);
++                    }
+                     if (accessedVariable instanceof VariableExpression) {
+                         VariableExpression var = (VariableExpression) accessedVariable;
+                         List<ClassNode> types = typeCheckingContext.ifElseForWhileAssignmentTracker.get(var);
+@@ -1947,40 +1962,48 @@
+     protected ClassNode[] getArgumentTypes(ArgumentListExpression args) {
+         List<Expression> arglist = args.getExpressions();
+         ClassNode[] ret = new ClassNode[arglist.size()];
+-        int i = 0;
+-        Map<Object, List<ClassNode>> info = typeCheckingContext.temporaryIfBranchTypeInformation.empty() ? null : typeCheckingContext.temporaryIfBranchTypeInformation.peek();
+-        for (Expression exp : arglist) {
+-            if (isNullConstant(exp)) {
++        for (int i = 0; i < arglist.size(); i++) {
++            if (isNullConstant(arglist.get(i))) {
+                 ret[i] = UNKNOWN_PARAMETER_TYPE;
+             } else {
+-                ret[i] = getType(exp);
+-                if (exp instanceof VariableExpression && info != null) {
+-                    List<ClassNode> classNodes = getTemporaryTypesForExpression(exp);
+-                    if (classNodes != null && !classNodes.isEmpty()) {
+-                        ArrayList<ClassNode> arr = new ArrayList<ClassNode>(classNodes.size() + 1);
+-                        arr.add(ret[i]);
+-                        arr.addAll(classNodes);
+-                        // GROOVY-7333: filter out Object
+-                        Iterator<ClassNode> iterator = arr.iterator();
+-                        while (iterator.hasNext()) {
+-                            ClassNode next = iterator.next();
+-                            if (ClassHelper.OBJECT_TYPE.equals(next)) {
+-                                iterator.remove();
+-                            }
+-                        }
+-                        if (arr.isEmpty()) {
+-                            ret[i] = ClassHelper.OBJECT_TYPE.getPlainNodeReference();
+-                        } else if (arr.size()==1) {
+-                            ret[i] = arr.get(0);
+-                        } else {
+-                            ret[i] = new UnionTypeClassNode(arr.toArray(new ClassNode[arr.size()]));
+-                        }
+-                    }
++                ret[i] = getInferredType(arglist.get(i));
++            }
++        }
++        return ret;
++    }
++
++    private ClassNode getInferredType(Expression exp) {
++        ClassNode result = getType(exp);
++        result = getInferredTypeFromTempInfo(exp, result);
++        return result;
++    }
++
++    private ClassNode getInferredTypeFromTempInfo(Expression exp, ClassNode result) {
++        Map<Object, List<ClassNode>> info = typeCheckingContext.temporaryIfBranchTypeInformation.empty() ? null : typeCheckingContext.temporaryIfBranchTypeInformation.peek();
++        if (exp instanceof VariableExpression && info != null) {
++            List<ClassNode> classNodes = getTemporaryTypesForExpression(exp);
++            if (classNodes != null && !classNodes.isEmpty()) {
++                ArrayList<ClassNode> arr = new ArrayList<ClassNode>(classNodes.size() + 1);
++                if (result != null) arr.add(result);
++                arr.addAll(classNodes);
++                // GROOVY-7333: filter out Object
++                Iterator<ClassNode> iterator = arr.iterator();
++                while (iterator.hasNext()) {
++                    ClassNode next = iterator.next();
++                    if (ClassHelper.OBJECT_TYPE.equals(next)) {
++                        iterator.remove();
++                    }
++                }
++                if (arr.isEmpty()) {
++                    result = ClassHelper.OBJECT_TYPE.getPlainNodeReference();
++                } else if (arr.size()==1) {
++                    result = arr.get(0);
++                } else {
++                    result = new UnionTypeClassNode(arr.toArray(new ClassNode[arr.size()]));
+                 }
+             }
+-            i++;
+         }
+-        return ret;
++        return result;
+     }
+ 
+     @Override
+@@ -4026,6 +4049,9 @@
+                 List<ClassNode> temporaryTypesForExpression = getTemporaryTypesForExpression(vexp);
+                 if (temporaryTypesForExpression == null || temporaryTypesForExpression.isEmpty()) {
+                     type = typeCheckingContext.controlStructureVariables.get(parameter);
++//                } else {
++//                    ClassNode temp = getInferredTypeFromTempInfo((Expression) exp, null);
++//                    type = temp;
+                 }
+                 // now check for closure override
+                 TypeCheckingContext.EnclosingClosure enclosingClosure = typeCheckingContext.getEnclosingClosure();
+@@ -4849,4 +4875,65 @@
+         }
+     }
+ 
++    /**
++     * Wrapper for a Parameter so it can be treated like a VariableExpression
++     * and tracked in the ifElseForWhileAssignmentTracker.
++     *
++     * This class purposely does not adhere to the normal equals and hashCode
++     * contract on the Object class and delegates those calls to the wrapped
++     * variable.
++     */
++    private static class ParameterVariableExpression extends VariableExpression {
++
++        private final Parameter parameter;
++
++        ParameterVariableExpression(Parameter parameter) {
++            super(parameter);
++            this.parameter = parameter;
++            ClassNode inferred = parameter.getNodeMetaData(StaticTypesMarker.INFERRED_TYPE);
++            if (inferred == null) {
++                parameter.setNodeMetaData(StaticTypesMarker.INFERRED_TYPE, parameter.getOriginType());
++            }
++        }
++
++        @Override
++        public void copyNodeMetaData(ASTNode other) {
++            parameter.copyNodeMetaData(other);
++        }
++
++        @Override
++        public Object putNodeMetaData(Object key, Object value) {
++            return parameter.putNodeMetaData(key, value);
++        }
++
++        @Override
++        public void removeNodeMetaData(Object key) {
++            parameter.removeNodeMetaData(key);
++        }
++
++        @Override
++        public Map<?, ?> getNodeMetaData() {
++            return parameter.getNodeMetaData();
++        }
++
++        @Override
++        public <T> T getNodeMetaData(Object key) {
++            return parameter.getNodeMetaData(key);
++        }
++
++        @Override
++        public void setNodeMetaData(Object key, Object value) {
++            parameter.setNodeMetaData(key, value);
++        }
++
++        @Override
++        public int hashCode() {
++            return parameter.hashCode();
++        }
++
++        @Override
++        public boolean equals(Object other) {
++            return parameter.equals(other);
++        }
++    }
+ }
+Index: src/test/groovy/transform/stc/STCAssignmentTest.groovy
+IDEA additional info:
+Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
+<+>UTF-8
+===================================================================
+--- src/test/groovy/transform/stc/STCAssignmentTest.groovy	(revision 456aa4dd37dbcebcfb263db2914b2d84246bc30f)
++++ src/test/groovy/transform/stc/STCAssignmentTest.groovy	(revision )
+@@ -446,6 +446,21 @@
+         ''', 'Cannot find matching method java.io.Serializable#toInteger()'
+     }
+ 
++    void testIfElseBranchParameter() {
++        shouldFailWithMessages '''
++            def foo(x) {
++                def y = 'foo'
++                if (y) {
++                    x = new HashSet()
++                } else {
++                    x = '123'
++                }
++                x.toInteger()
++            }
++            foo('bar')
++        ''', 'Cannot find matching method java.lang.Object#toInteger()'
++    }
++
+     void testIfOnly() {
+         shouldFailWithMessages '''
+             def x = '123'
+@@ -457,6 +472,20 @@
+         ''', 'Cannot find matching method java.io.Serializable#toInteger()'
+     }
+ 
++    void testIfOnlyParameter() {
++        shouldFailWithMessages '''
++            def foo(x) {
++                def y = 'foo'
++                if (y) {
++                    x = new HashSet()
++                    assert x.isEmpty()
++                }
++                x.toInteger()
++            }
++            foo('123')
++        ''', 'Cannot find matching method java.lang.Object#toInteger()'
++    }
++
+     void testIfWithCommonInterface() {
+         assertScript '''
+             interface Foo { void foo() }
+@@ -872,5 +901,63 @@
+         }            
+         '''
+     }
+-}
++
++    // GROOVY-8220
++    void testFlowTypingParameterTempTypeAssignmentTracking() {
++        assertScript '''
++            class Foo {
++                CharSequence makeEnv( env, StringBuilder result = new StringBuilder() ) {
++                    if (env instanceof File) {
++                        env = env.toPath()
++                    }
++                    if (env instanceof String && env.contains('=')) {
++                        result << 'export ' << env << ';'
++                    }
++                    return result.toString()
++                }
++            }
++            assert new Foo().makeEnv('X=1') == 'export X=1;'
++        '''
++        // GROOVY-8237
++        assertScript '''
++            class Foo {
++                String parse(Reader reader) {
++                    if (reader == null)
++                        reader = new BufferedReader(reader)
++                    int i = reader.read()
++                    return (i != -1) ? 'bar' : 'baz'
++                }
++            }
++            assert new Foo().parse(new StringReader('foo')) == 'bar'
++        '''
++    }
+ 
++    void testFlowTypingParameterTempTypeAssignmentTrackingWithGenerics() {
++        assertScript '''
++            class M {
++                Map<String, List<Object>> mvm = new HashMap<String, List<Object>>()
++                void setProperty(String name, value) {
++                    if (value instanceof File) {
++                        value = new File(value, 'bar.txt')
++                    }
++                    else if (value instanceof URL) {
++                        value = value.toURI()
++                    }
++                    else if (value instanceof InputStream) {
++                        value = new BufferedInputStream(value)
++                    }
++                    else if (value instanceof GString) {
++                        value = value.toString()
++                    }
++                    if (mvm[name]) {
++                        mvm[name].add value
++                    } else {
++                        mvm.put(name, [value])
++                    }
++                }
++            }
++            new M().setProperty('foo', 'bar')
++        '''
++    }
++
++}

http://git-wip-us.apache.org/repos/asf/groovy/blob/13522f88/groovy8260c.patch
----------------------------------------------------------------------
diff --git a/groovy8260c.patch b/groovy8260c.patch
new file mode 100644
index 0000000..f7598cd
--- /dev/null
+++ b/groovy8260c.patch
@@ -0,0 +1,188 @@
+commit 26d11337cfa4d66eed6eca1f99f5a5309427ebd9
+Author: paulk <pa...@asert.com.au>
+Date:   Fri Sep 29 22:35:54 2017 +1000
+
+    GROOVY-8260: Static compilation requires casting inside instanceof check (handle additional cases)
+
+diff --git a/src/main/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java b/src/main/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
+index 807449a1a..bda414bb8 100644
+--- a/src/main/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
++++ b/src/main/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
+@@ -480,7 +480,30 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
+             }
+         }
+ 
+-        if (! (vexp.getAccessedVariable() instanceof DynamicVariable)) return;
++        if (!(vexp.getAccessedVariable() instanceof DynamicVariable)) {
++            VariableExpression variable = null;
++            if (vexp.getAccessedVariable() instanceof Parameter) {
++                variable = new ParameterVariableExpression((Parameter) vexp.getAccessedVariable());
++            } else if (vexp.getAccessedVariable() instanceof VariableExpression) {
++                variable = (VariableExpression) vexp.getAccessedVariable();
++            }
++            if (variable != null) {
++                ClassNode inferredType = getInferredTypeFromTempInfo(variable, variable.getNodeMetaData(StaticTypesMarker.INFERRED_TYPE));
++                if (inferredType != null && !inferredType.getName().equals("java.lang.Object")) {
++                    if (typeCheckingContext.getEnclosingBinaryExpression() != null) {
++                        // TODO narrow this down to assignment
++                        if (typeCheckingContext.getEnclosingBinaryExpression().getRightExpression() == vexp) {
++                            vexp.putNodeMetaData(StaticTypesMarker.INFERRED_TYPE, inferredType);
++                        }
++                    } else {
++                        // stash away type info that will be lost later to handle case
++                        // where this expression has return added later - piggy back on existing key
++                        vexp.putNodeMetaData(StaticTypesMarker.INFERRED_RETURN_TYPE, inferredType);
++                    }
++                }
++            }
++            return;
++        }
+ 
+         // a dynamic variable is either an undeclared variable
+         // or a member of a class used in a 'with'
+@@ -1833,6 +1856,9 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
+         if (typeCheckingContext.getEnclosingClosure()!=null) {
+             return type;
+         }
++        if ((expression instanceof VariableExpression) && hasInferredReturnType(expression)) {
++            type = expression.getNodeMetaData(StaticTypesMarker.INFERRED_RETURN_TYPE);
++        }
+         MethodNode enclosingMethod = typeCheckingContext.getEnclosingMethod();
+         if (enclosingMethod != null && typeCheckingContext.getEnclosingClosure()==null) {
+             if (!enclosingMethod.isVoidMethod()
+@@ -3205,7 +3231,9 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
+         int depth = typeCheckingContext.temporaryIfBranchTypeInformation.size();
+         while (classNodes == null && depth > 0) {
+             final Map<Object, List<ClassNode>> tempo = typeCheckingContext.temporaryIfBranchTypeInformation.get(--depth);
+-            Object key = extractTemporaryTypeInfoKey(objectExpression);
++            Object key = objectExpression instanceof ParameterVariableExpression
++                    ? ((ParameterVariableExpression) objectExpression).parameter
++                    : extractTemporaryTypeInfoKey(objectExpression);
+             classNodes = tempo.get(key);
+         }
+         return classNodes;
+@@ -3393,6 +3421,14 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
+         typeCheckingContext.popTemporaryTypeInfo();
+         falseExpression.visit(this);
+         ClassNode resultType;
++        ClassNode typeOfFalse = getType(falseExpression);
++        ClassNode typeOfTrue = getType(trueExpression);
++        if (hasInferredReturnType(falseExpression)) {
++            typeOfFalse = falseExpression.getNodeMetaData(StaticTypesMarker.INFERRED_RETURN_TYPE);
++        }
++        if (hasInferredReturnType(trueExpression)) {
++            typeOfTrue = trueExpression.getNodeMetaData(StaticTypesMarker.INFERRED_RETURN_TYPE);
++        }
+         if (isNullConstant(trueExpression) || isNullConstant(falseExpression)) {
+             BinaryExpression enclosingBinaryExpression = typeCheckingContext.getEnclosingBinaryExpression();
+             if (enclosingBinaryExpression != null && enclosingBinaryExpression.getRightExpression()==expression) {
+@@ -3400,20 +3436,23 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
+             } else if (isNullConstant(trueExpression) && isNullConstant(falseExpression)) {
+                 resultType = OBJECT_TYPE;
+             } else if (isNullConstant(trueExpression)) {
+-                resultType = wrapTypeIfNecessary(getType(falseExpression));
++                resultType = wrapTypeIfNecessary(typeOfFalse);
+             } else {
+-                resultType = wrapTypeIfNecessary(getType(trueExpression));
++                resultType = wrapTypeIfNecessary(typeOfTrue);
+             }
+         } else {
+             // store type information
+-            final ClassNode typeOfTrue = getType(trueExpression);
+-            final ClassNode typeOfFalse = getType(falseExpression);
+             resultType = lowestUpperBound(typeOfTrue, typeOfFalse);
+         }
+         storeType(expression, resultType);
+         popAssignmentTracking(oldTracker);
+     }
+ 
++    private boolean hasInferredReturnType(Expression expression) {
++        ClassNode type = expression.getNodeMetaData(StaticTypesMarker.INFERRED_RETURN_TYPE);
++        return type != null && !type.getName().equals("java.lang.Object");
++    }
++
+     @Override
+     public void visitTryCatchFinally(final TryCatchStatement statement) {
+         final List<CatchStatement> catchStatements = statement.getCatchStatements();
+diff --git a/src/test/groovy/transform/stc/MiscSTCTest.groovy b/src/test/groovy/transform/stc/MiscSTCTest.groovy
+index 13bdb40c6..fadac0afa 100644
+--- a/src/test/groovy/transform/stc/MiscSTCTest.groovy
++++ b/src/test/groovy/transform/stc/MiscSTCTest.groovy
+@@ -22,8 +22,6 @@ import org.codehaus.groovy.transform.stc.StaticTypeCheckingVisitor
+ 
+ /**
+  * Unit tests for static type checking : miscellaneous tests.
+- *
+- * @author Cedric Champeau
+  */
+ class MiscSTCTest extends StaticTypeCheckingTestCase {
+ 
+@@ -272,8 +270,67 @@ class MiscSTCTest extends StaticTypeCheckingTestCase {
+         }
+     }
+ 
+-    public static class MiscSTCTestSupport {
++    static class MiscSTCTestSupport {
+         static def foo() { '123' }
+     }
++
++    void testTernaryParam() {
++        assertScript '''
++            Date ternaryParam(Object input) {
++                input instanceof Date ? input : null
++            }
++            def d = new Date()
++            assert ternaryParam(42) == null
++            assert ternaryParam('foo') == null
++            assert ternaryParam(d) == d
++        '''
++    }
++
++    void testTernaryLocalVar() {
++        assertScript '''
++            Date ternaryLocalVar(Object input) {
++                Object copy = input
++                copy instanceof Date ? copy : null
++            }
++            def d = new Date()
++            assert ternaryLocalVar(42) == null
++            assert ternaryLocalVar('foo') == null
++            assert ternaryLocalVar(d) == d
++        '''
++    }
++
++    void testIfThenElseParam() {
++        assertScript '''
++            Date ifThenElseParam(Object input) {
++                if (input instanceof Date) {
++                    input
++                } else {
++                    null
++                }
++            }
++            def d = new Date()
++            assert ifThenElseParam(42) == null
++            assert ifThenElseParam('foo') == null
++            assert ifThenElseParam(d) == d
++        '''
++    }
++
++    void testIfThenElseLocalVar() {
++        assertScript '''
++            Date ifThenElseLocalVar(Object input) {
++                Date result
++                if (input instanceof Date) {
++                    result = input
++                } else {
++                    result = null
++                }
++                result
++            }
++            def d = new Date()
++            assert ifThenElseLocalVar(42) == null
++            assert ifThenElseLocalVar('foo') == null
++            assert ifThenElseLocalVar(d) == d
++        '''
++    }
+ }
+ 

http://git-wip-us.apache.org/repos/asf/groovy/blob/13522f88/ivy_snapshot.patch
----------------------------------------------------------------------
diff --git a/ivy_snapshot.patch b/ivy_snapshot.patch
new file mode 100644
index 0000000..3ce0c68
--- /dev/null
+++ b/ivy_snapshot.patch
@@ -0,0 +1,24 @@
+Index: build.gradle
+IDEA additional info:
+Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
+<+>UTF-8
+===================================================================
+--- build.gradle	(revision 8301ba03d2a38b36b9f718db54f46b935e1aba5d)
++++ build.gradle	(revision )
+@@ -94,6 +94,7 @@
+         }
+         jcenter()
+         maven { url 'http://dl.bintray.com/melix/thirdparty-apache' } // openbeans
++        maven { url 'https://repository.apache.org/snapshots/' }
+     }
+ 
+     apply plugin: 'groovy'
+@@ -168,7 +169,7 @@
+     eclipseOsgiVersion = '3.9.1-v20140110-1610'
+     gparsVersion = '1.2.1'
+     gradleVersion = '3.5.1'
+-    ivyVersion = '2.4.0'
++    ivyVersion = '2.5.0-SNAPSHOT'
+     jansiVersion = '1.13'
+     jarjarVersion = '1.4.1'
+     jlineVersion = '2.14.5'

http://git-wip-us.apache.org/repos/asf/groovy/blob/13522f88/pr502.patch
----------------------------------------------------------------------
diff --git a/pr502.patch b/pr502.patch
new file mode 100644
index 0000000..b63c727
--- /dev/null
+++ b/pr502.patch
@@ -0,0 +1,118 @@
+From 764388a34b9f6fbf1c605fbbf02700b8ebed82d8 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Christoffer=20Hammarstr=C3=B6m?=
+ <ch...@linuxgods.com>
+Date: Wed, 22 Feb 2017 02:18:52 +0100
+Subject: [PATCH] Add tests to prove that calling
+ CompilerConfiguration.setScriptBaseClass with a Java class causes ModuleNode
+ to generate a constructor that prevents Field initialization from Binding
+ context.
+
+---
+ src/test/groovy/lang/BindingScript.java      | 32 +++++++++++++++++
+ src/test/groovy/lang/GroovyShellTest2.groovy | 54 ++++++++++++++++++++++++++++
+ 2 files changed, 86 insertions(+)
+ create mode 100644 src/test/groovy/lang/BindingScript.java
+
+diff --git a/src/test/groovy/lang/BindingScript.java b/src/test/groovy/lang/BindingScript.java
+new file mode 100644
+index 0000000..81cda00
+--- /dev/null
++++ b/src/test/groovy/lang/BindingScript.java
+@@ -0,0 +1,32 @@
++/*
++ *  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 Script which requires a Binding passed in the constructor and disallows calling the default constructor.
++ */
++public abstract class BindingScript extends Script {
++    protected BindingScript() {
++        throw new UnsupportedOperationException("\n\t*******\n\tBindingScript() should not be called! Should be calling BindingScript(Binding)!\n\t*******");
++    }
++
++    protected BindingScript(Binding binding) {
++        super(binding);
++    }
++}
+diff --git a/src/test/groovy/lang/GroovyShellTest2.groovy b/src/test/groovy/lang/GroovyShellTest2.groovy
+index 27259bf..c883553 100644
+--- a/src/test/groovy/lang/GroovyShellTest2.groovy
++++ b/src/test/groovy/lang/GroovyShellTest2.groovy
+@@ -43,6 +43,60 @@ class GroovyShellTest2 extends GroovyTestCase {
+         assert result == arg0
+     }
+ 
++    void testBindingsInFieldInitializersWithAnnotatedJavaBaseScript() {
++        def shell = new GroovyShell();
++        def scriptText = '''
++        @groovy.transform.BaseScript groovy.lang.BindingScript baseScript
++        @groovy.transform.Field def script_args = getProperty('args')
++
++        assert script_args[0] == 'Hello Groovy'
++        script_args[0]
++'''
++
++        def arg0 = 'Hello Groovy'
++        def result = shell.run scriptText, 'TestBindingsInFieldInitializersWithAnnotatedJavaBaseScript.groovy', [arg0]
++        assert result == arg0
++    }
++
++    /**
++     This test fails because {@link org.codehaus.groovy.ast.ModuleNode#setScriptBaseClassFromConfig(org.codehaus.groovy.ast.ClassNode)}
++     calls .setSuperClass(ClassHelper.make(baseClassName)) on the Scripts ClassNode.
++
++     The ClassNode created for this scriptBaseClass has lazyInitDone = true and constructors = null so when
++     .getSuperClass().getDeclaredConstructor(SCRIPT_CONTEXT_CTOR) is called by {@link org.codehaus.groovy.ast.ModuleNode#createStatementsClass()}
++     then ClassNode.constructors is set to an empty ArrayList in {@link org.codehaus.groovy.ast.ClassNode#getDeclaredConstructors()}
++
++     The script constructor is then generated as
++         Constructor(Binding context) {
++             super();                                    // Fields are initialized after the call to super()
++             setBinding(context);                        // Fields are initalized before the call to setBinding(context)
++         }
++
++     instead of
++         Constructor(Binding context) {
++             super(context);                             // Fields are initialized after the call to super(context)
++         }
++
++     Fields are initialized between the call to super() and the setBinding(context)
++     which means Field initializers don't have access to the Binding context.
++     */
++    void testBindingsInFieldInitializersWithConfigJavaBaseScript() {
++        def config = new org.codehaus.groovy.control.CompilerConfiguration()
++        config.scriptBaseClass = BindingScript.class.name
++
++        def shell = new GroovyShell(config);
++        def scriptText = '''
++        @groovy.transform.Field def script_args = getProperty('args')
++
++        assert script_args[0] == 'Hello Groovy'
++        script_args[0]
++'''
++
++        def arg0 = 'Hello Groovy'
++        def result = shell.run scriptText, 'TestBindingsInFieldInitializersWithConfigJavaBaseScript.groovy', [arg0]
++        assert result == arg0
++    }
++
+     void testBindingsInScriptFieldInitializers() {
+         def shell = new GroovyShell();
+         def scriptText = '''

http://git-wip-us.apache.org/repos/asf/groovy/blob/13522f88/pr507.patch
----------------------------------------------------------------------
diff --git a/pr507.patch b/pr507.patch
new file mode 100644
index 0000000..72d74a1
--- /dev/null
+++ b/pr507.patch
@@ -0,0 +1,25 @@
+From: AarjavP <Aa...@users.noreply.github.com>
+Date: Wed, 30 Aug 2017 17:39:44 +0200
+Subject: [PATCH] Fix wildcard arg handling in startGroovy.bat (closes #507)
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Aarjav Patel
+---
+ src/bin/startGroovy.bat | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/src/bin/startGroovy.bat b/src/bin/startGroovy.bat
+index 1b7988218..f869ff7938b5a4262be297007178ef6f68aafaff 100644
+--- a/src/bin/startGroovy.bat
++++ b/src/bin/startGroovy.bat
+@@ -177,7 +177,7 @@
+ goto process_arg
+ 
+ :get_arg
+-rem remove quotes around first arg
++rem remove quotes around first arg and don't expand wildcards
+ for /f %%i in (%1) do set _ARG=%_ARG% %%~i
+ rem set the remaining args
+ set _ARGS=%2

http://git-wip-us.apache.org/repos/asf/groovy/blob/13522f88/pr555.patch
----------------------------------------------------------------------
diff --git a/pr555.patch b/pr555.patch
new file mode 100644
index 0000000..67423c6
--- /dev/null
+++ b/pr555.patch
@@ -0,0 +1,312 @@
+From 11a0b159d8d04f3c1e518613566a1b459ecda44d Mon Sep 17 00:00:00 2001
+From: noamt <no...@10ne.org>
+Date: Wed, 31 May 2017 20:57:04 +0200
+Subject: [PATCH 1/5] GROOVY-8200 - Shorthand |= results in NPE: Fixing the NPE
+ with an explicit test and assignment of the right-hand boolean operator.
+ Assigning a primitive boolean variable with null, like `boolean x = null`,
+ will end up as `false`. I think it only makes sense to apply the same
+ behavior to the right hand operator.
+
+---
+ .../groovy/runtime/DefaultGroovyMethods.java       | 12 ++++++++
+ .../groovy/runtime/DefaultGroovyMethodsTest.groovy | 36 ++++++++++++++++++++++
+ 2 files changed, 48 insertions(+)
+
+diff --git a/src/main/org/codehaus/groovy/runtime/DefaultGroovyMethods.java b/src/main/org/codehaus/groovy/runtime/DefaultGroovyMethods.java
+index 76b9fa6378..da50255833 100644
+--- a/src/main/org/codehaus/groovy/runtime/DefaultGroovyMethods.java
++++ b/src/main/org/codehaus/groovy/runtime/DefaultGroovyMethods.java
+@@ -15760,6 +15760,9 @@ public static BigInteger toBigInteger(Number self) {
+      * @since 1.0
+      */
+     public static Boolean and(Boolean left, Boolean right) {
++        if (right == null) {
++            right = Boolean.FALSE;
++        }
+         return left && right;
+     }
+ 
+@@ -15772,6 +15775,9 @@ public static Boolean and(Boolean left, Boolean right) {
+      * @since 1.0
+      */
+     public static Boolean or(Boolean left, Boolean right) {
++        if (right == null) {
++            right = Boolean.FALSE;
++        }
+         return left || right;
+     }
+ 
+@@ -15784,6 +15790,9 @@ public static Boolean or(Boolean left, Boolean right) {
+      * @since 1.8.3
+      */
+     public static Boolean implies(Boolean left, Boolean right) {
++        if (right == null) {
++            right = Boolean.FALSE;
++        }
+         return !left || right;
+     }
+ 
+@@ -15796,6 +15805,9 @@ public static Boolean implies(Boolean left, Boolean right) {
+      * @since 1.0
+      */
+     public static Boolean xor(Boolean left, Boolean right) {
++        if (right == null) {
++            right = Boolean.FALSE;
++        }
+         return left ^ right;
+     }
+ 
+diff --git a/src/test/org/codehaus/groovy/runtime/DefaultGroovyMethodsTest.groovy b/src/test/org/codehaus/groovy/runtime/DefaultGroovyMethodsTest.groovy
+index 087b301bc3..c0e4e1a990 100644
+--- a/src/test/org/codehaus/groovy/runtime/DefaultGroovyMethodsTest.groovy
++++ b/src/test/org/codehaus/groovy/runtime/DefaultGroovyMethodsTest.groovy
+@@ -239,4 +239,40 @@ public class DefaultGroovyMethodsTest extends GroovyTestCase {
+     private static class MyList extends ArrayList {
+         public MyList() {}
+     }
++
++    public void testBooleanOr() {
++        assertTrue(DefaultGroovyMethods.or(true, true))
++        assertTrue(DefaultGroovyMethods.or(true, false))
++        assertTrue(DefaultGroovyMethods.or(false, true))
++        assertFalse(DefaultGroovyMethods.or(false, false))
++        assertFalse(DefaultGroovyMethods.or(false, null))
++        assertTrue(DefaultGroovyMethods.or(true, null))
++    }
++
++    public void testBooleanAnd() {
++        assertTrue(DefaultGroovyMethods.and(true, true))
++        assertFalse(DefaultGroovyMethods.and(true, false))
++        assertFalse(DefaultGroovyMethods.and(false, true))
++        assertFalse(DefaultGroovyMethods.and(false, false))
++        assertFalse(DefaultGroovyMethods.and(false, null))
++        assertFalse(DefaultGroovyMethods.and(true, null))
++    }
++
++    public void testBooleanXor() {
++        assertFalse(DefaultGroovyMethods.xor(true, true))
++        assertTrue(DefaultGroovyMethods.xor(true, false))
++        assertTrue(DefaultGroovyMethods.xor(false, true))
++        assertFalse(DefaultGroovyMethods.xor(false, false))
++        assertFalse(DefaultGroovyMethods.xor(false, null))
++        assertTrue(DefaultGroovyMethods.xor(true, null))
++    }
++
++    public void testBooleanImplication() {
++        assertTrue(DefaultGroovyMethods.implies(true, true))
++        assertTrue(DefaultGroovyMethods.xor(true, false))
++        assertTrue(DefaultGroovyMethods.xor(false, true))
++        assertFalse(DefaultGroovyMethods.xor(false, false))
++        assertFalse(DefaultGroovyMethods.xor(false, null))
++        assertTrue(DefaultGroovyMethods.xor(true, null))
++    }
+ }
+
+From 2d8fc8957a82658ec000e77cb1cab66565ef2a6a Mon Sep 17 00:00:00 2001
+From: noamt <no...@10ne.org>
+Date: Thu, 1 Jun 2017 15:02:40 +0200
+Subject: [PATCH 2/5] GROOVY-8200 - Shorthand |= results in NPE: Using a
+ cleaner, safe assignment of the right hand operator
+
+---
+ .../codehaus/groovy/runtime/DefaultGroovyMethods.java    | 16 ++++------------
+ 1 file changed, 4 insertions(+), 12 deletions(-)
+
+diff --git a/src/main/org/codehaus/groovy/runtime/DefaultGroovyMethods.java b/src/main/org/codehaus/groovy/runtime/DefaultGroovyMethods.java
+index da50255833..f359f44dfd 100644
+--- a/src/main/org/codehaus/groovy/runtime/DefaultGroovyMethods.java
++++ b/src/main/org/codehaus/groovy/runtime/DefaultGroovyMethods.java
+@@ -15760,9 +15760,7 @@ public static BigInteger toBigInteger(Number self) {
+      * @since 1.0
+      */
+     public static Boolean and(Boolean left, Boolean right) {
+-        if (right == null) {
+-            right = Boolean.FALSE;
+-        }
++        right = Boolean.TRUE.equals(right);
+         return left && right;
+     }
+ 
+@@ -15775,9 +15773,7 @@ public static Boolean and(Boolean left, Boolean right) {
+      * @since 1.0
+      */
+     public static Boolean or(Boolean left, Boolean right) {
+-        if (right == null) {
+-            right = Boolean.FALSE;
+-        }
++        right = Boolean.TRUE.equals(right);
+         return left || right;
+     }
+ 
+@@ -15790,9 +15786,7 @@ public static Boolean or(Boolean left, Boolean right) {
+      * @since 1.8.3
+      */
+     public static Boolean implies(Boolean left, Boolean right) {
+-        if (right == null) {
+-            right = Boolean.FALSE;
+-        }
++        right = Boolean.TRUE.equals(right);
+         return !left || right;
+     }
+ 
+@@ -15805,9 +15799,7 @@ public static Boolean implies(Boolean left, Boolean right) {
+      * @since 1.0
+      */
+     public static Boolean xor(Boolean left, Boolean right) {
+-        if (right == null) {
+-            right = Boolean.FALSE;
+-        }
++        right = Boolean.TRUE.equals(right);
+         return left ^ right;
+     }
+ 
+
+From 9d9f2d49db0cd149349b74549f5556a650bc5c7f Mon Sep 17 00:00:00 2001
+From: noamt <no...@10ne.org>
+Date: Wed, 7 Jun 2017 12:33:13 +0300
+Subject: [PATCH 3/5] GROOVY-8200 - Shorthand |= results in NPE: Reducing the
+ expression to a one liner
+
+---
+ .../org/codehaus/groovy/runtime/DefaultGroovyMethods.java    | 12 ++++--------
+ 1 file changed, 4 insertions(+), 8 deletions(-)
+
+diff --git a/src/main/org/codehaus/groovy/runtime/DefaultGroovyMethods.java b/src/main/org/codehaus/groovy/runtime/DefaultGroovyMethods.java
+index f359f44dfd..193a7bf655 100644
+--- a/src/main/org/codehaus/groovy/runtime/DefaultGroovyMethods.java
++++ b/src/main/org/codehaus/groovy/runtime/DefaultGroovyMethods.java
+@@ -15760,8 +15760,7 @@ public static BigInteger toBigInteger(Number self) {
+      * @since 1.0
+      */
+     public static Boolean and(Boolean left, Boolean right) {
+-        right = Boolean.TRUE.equals(right);
+-        return left && right;
++        return left && Boolean.TRUE.equals(right);
+     }
+ 
+     /**
+@@ -15773,8 +15772,7 @@ public static Boolean and(Boolean left, Boolean right) {
+      * @since 1.0
+      */
+     public static Boolean or(Boolean left, Boolean right) {
+-        right = Boolean.TRUE.equals(right);
+-        return left || right;
++        return left || Boolean.TRUE.equals(right);
+     }
+ 
+     /**
+@@ -15786,8 +15784,7 @@ public static Boolean or(Boolean left, Boolean right) {
+      * @since 1.8.3
+      */
+     public static Boolean implies(Boolean left, Boolean right) {
+-        right = Boolean.TRUE.equals(right);
+-        return !left || right;
++        return !left || Boolean.TRUE.equals(right);
+     }
+ 
+     /**
+@@ -15799,8 +15796,7 @@ public static Boolean implies(Boolean left, Boolean right) {
+      * @since 1.0
+      */
+     public static Boolean xor(Boolean left, Boolean right) {
+-        right = Boolean.TRUE.equals(right);
+-        return left ^ right;
++        return left ^ Boolean.TRUE.equals(right);
+     }
+ 
+ //    public static Boolean negate(Boolean left) {
+
+From aa715bcc38fa2cfb13de7cbccbda5c6aaba2cf14 Mon Sep 17 00:00:00 2001
+From: noamt <no...@10ne.org>
+Date: Thu, 8 Jun 2017 14:03:19 +0300
+Subject: [PATCH 4/5] GROOVY-8200 - Shorthand |= results in NPE: Fix copy-pasta
+ mistake in DefaultGroovyMethodsTest
+
+---
+ .../codehaus/groovy/runtime/DefaultGroovyMethodsTest.groovy    | 10 +++++-----
+ 1 file changed, 5 insertions(+), 5 deletions(-)
+
+diff --git a/src/test/org/codehaus/groovy/runtime/DefaultGroovyMethodsTest.groovy b/src/test/org/codehaus/groovy/runtime/DefaultGroovyMethodsTest.groovy
+index c0e4e1a990..713e29b431 100644
+--- a/src/test/org/codehaus/groovy/runtime/DefaultGroovyMethodsTest.groovy
++++ b/src/test/org/codehaus/groovy/runtime/DefaultGroovyMethodsTest.groovy
+@@ -269,10 +269,10 @@ public class DefaultGroovyMethodsTest extends GroovyTestCase {
+ 
+     public void testBooleanImplication() {
+         assertTrue(DefaultGroovyMethods.implies(true, true))
+-        assertTrue(DefaultGroovyMethods.xor(true, false))
+-        assertTrue(DefaultGroovyMethods.xor(false, true))
+-        assertFalse(DefaultGroovyMethods.xor(false, false))
+-        assertFalse(DefaultGroovyMethods.xor(false, null))
+-        assertTrue(DefaultGroovyMethods.xor(true, null))
++        assertFalse(DefaultGroovyMethods.implies(true, false))
++        assertTrue(DefaultGroovyMethods.implies(false, true))
++        assertTrue(DefaultGroovyMethods.implies(false, false))
++        assertTrue(DefaultGroovyMethods.implies(false, null))
++        assertFalse(DefaultGroovyMethods.implies(true, null))
+     }
+ }
+
+From 0e95399596b828c1ad14f571290e79ad03eef2b2 Mon Sep 17 00:00:00 2001
+From: noamt <no...@10ne.org>
+Date: Thu, 8 Jun 2017 14:04:06 +0300
+Subject: [PATCH 5/5] GROOVY-8200 - Shorthand |= results in NPE: Adding tests
+ for the shorthand logical operators
+
+---
+ src/spec/test/OperatorsTest.groovy | 44 +++++++++++++++++++++++++++++++++++++-
+ 1 file changed, 43 insertions(+), 1 deletion(-)
+
+diff --git a/src/spec/test/OperatorsTest.groovy b/src/spec/test/OperatorsTest.groovy
+index a0eddf38d8..46b87f7e7b 100644
+--- a/src/spec/test/OperatorsTest.groovy
++++ b/src/spec/test/OperatorsTest.groovy
+@@ -607,4 +607,46 @@ assert (b1 + 11).size == 15
+             assert str1 == str2
+             '''
+     }
+-}
++
++    void testBooleanOr() {
++        assertScript '''
++boolean trueValue1 = true, trueValue2 = true, trueValue3 = true
++boolean falseValue1 = false, falseValue2 = false, falseValue3 = false
++
++assert (trueValue1 |= true)
++assert (trueValue2 |= false)
++assert (trueValue3 |= null)
++assert (falseValue1 |= true)
++assert !(falseValue2 |= false)
++assert !(falseValue3 |= null)
++'''
++    }
++
++    void testBooleanAnd() {
++        assertScript '''
++boolean trueValue1 = true, trueValue2 = true, trueValue3 = true
++boolean falseValue1 = false, falseValue2 = false, falseValue3 = false
++
++assert (trueValue1 &= true)
++assert !(trueValue2 &= false)
++assert !(trueValue3 &= null)
++assert !(falseValue1 &= true)
++assert !(falseValue2 &= false)
++assert !(falseValue3 &= null)
++'''
++    }
++
++    void testBooleanXor() {
++        assertScript '''
++boolean trueValue1 = true, trueValue2 = true, trueValue3 = true
++boolean falseValue1 = false, falseValue2 = false, falseValue3 = false
++
++assert !(trueValue1 ^= true)
++assert (trueValue2 ^= false)
++assert (trueValue3 ^= null)
++assert (falseValue1 ^= true)
++assert !(falseValue2 ^= false)
++assert !(falseValue3 ^= null)
++'''
++    }
++}
+\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/groovy/blob/13522f88/pr555a.patch
----------------------------------------------------------------------
diff --git a/pr555a.patch b/pr555a.patch
new file mode 100644
index 0000000..9e54187
--- /dev/null
+++ b/pr555a.patch
@@ -0,0 +1,94 @@
+ .../groovy/runtime/DefaultGroovyMethods.java       | 12 ++++++++
+ .../groovy/runtime/DefaultGroovyMethodsTest.groovy | 36 ++++++++++++++++++++++
+ 2 files changed, 48 insertions(+)
+
+diff --git a/src/main/org/codehaus/groovy/runtime/DefaultGroovyMethods.java b/src/main/org/codehaus/groovy/runtime/DefaultGroovyMethods.java
+index 76b9fa6378..da50255833 100644
+--- a/src/main/org/codehaus/groovy/runtime/DefaultGroovyMethods.java
++++ b/src/main/org/codehaus/groovy/runtime/DefaultGroovyMethods.java
+@@ -15760,6 +15760,9 @@ public static BigInteger toBigInteger(Number self) {
+      * @since 1.0
+      */
+     public static Boolean and(Boolean left, Boolean right) {
++        if (right == null) {
++            right = Boolean.FALSE;
++        }
+         return left && right;
+     }
+ 
+@@ -15772,6 +15775,9 @@ public static Boolean and(Boolean left, Boolean right) {
+      * @since 1.0
+      */
+     public static Boolean or(Boolean left, Boolean right) {
++        if (right == null) {
++            right = Boolean.FALSE;
++        }
+         return left || right;
+     }
+ 
+@@ -15784,6 +15790,9 @@ public static Boolean or(Boolean left, Boolean right) {
+      * @since 1.8.3
+      */
+     public static Boolean implies(Boolean left, Boolean right) {
++        if (right == null) {
++            right = Boolean.FALSE;
++        }
+         return !left || right;
+     }
+ 
+@@ -15796,6 +15805,9 @@ public static Boolean implies(Boolean left, Boolean right) {
+      * @since 1.0
+      */
+     public static Boolean xor(Boolean left, Boolean right) {
++        if (right == null) {
++            right = Boolean.FALSE;
++        }
+         return left ^ right;
+     }
+ 
+diff --git a/src/test/org/codehaus/groovy/runtime/DefaultGroovyMethodsTest.groovy b/src/test/org/codehaus/groovy/runtime/DefaultGroovyMethodsTest.groovy
+index 087b301bc3..c0e4e1a990 100644
+--- a/src/test/org/codehaus/groovy/runtime/DefaultGroovyMethodsTest.groovy
++++ b/src/test/org/codehaus/groovy/runtime/DefaultGroovyMethodsTest.groovy
+@@ -239,4 +239,40 @@ public class DefaultGroovyMethodsTest extends GroovyTestCase {
+     private static class MyList extends ArrayList {
+         public MyList() {}
+     }
++
++    public void testBooleanOr() {
++        assertTrue(DefaultGroovyMethods.or(true, true))
++        assertTrue(DefaultGroovyMethods.or(true, false))
++        assertTrue(DefaultGroovyMethods.or(false, true))
++        assertFalse(DefaultGroovyMethods.or(false, false))
++        assertFalse(DefaultGroovyMethods.or(false, null))
++        assertTrue(DefaultGroovyMethods.or(true, null))
++    }
++
++    public void testBooleanAnd() {
++        assertTrue(DefaultGroovyMethods.and(true, true))
++        assertFalse(DefaultGroovyMethods.and(true, false))
++        assertFalse(DefaultGroovyMethods.and(false, true))
++        assertFalse(DefaultGroovyMethods.and(false, false))
++        assertFalse(DefaultGroovyMethods.and(false, null))
++        assertFalse(DefaultGroovyMethods.and(true, null))
++    }
++
++    public void testBooleanXor() {
++        assertFalse(DefaultGroovyMethods.xor(true, true))
++        assertTrue(DefaultGroovyMethods.xor(true, false))
++        assertTrue(DefaultGroovyMethods.xor(false, true))
++        assertFalse(DefaultGroovyMethods.xor(false, false))
++        assertFalse(DefaultGroovyMethods.xor(false, null))
++        assertTrue(DefaultGroovyMethods.xor(true, null))
++    }
++
++    public void testBooleanImplication() {
++        assertTrue(DefaultGroovyMethods.implies(true, true))
++        assertTrue(DefaultGroovyMethods.xor(true, false))
++        assertTrue(DefaultGroovyMethods.xor(false, true))
++        assertFalse(DefaultGroovyMethods.xor(false, false))
++        assertFalse(DefaultGroovyMethods.xor(false, null))
++        assertTrue(DefaultGroovyMethods.xor(true, null))
++    }
+ }
+

http://git-wip-us.apache.org/repos/asf/groovy/blob/13522f88/pr565.patch
----------------------------------------------------------------------
diff --git a/pr565.patch b/pr565.patch
new file mode 100644
index 0000000..31c7ce7
--- /dev/null
+++ b/pr565.patch
@@ -0,0 +1,168 @@
+From b3a0e1634749dbd703f705795a767b71c11a7bec Mon Sep 17 00:00:00 2001
+From: paulk <pa...@asert.com.au>
+Date: Sun, 25 Jun 2017 21:57:36 +1000
+Subject: [PATCH] GROOVY-8236: Report more meaningful error for versions of
+ Groovy not supporting @Repeatable
+
+---
+ .../codehaus/groovy/classgen/ExtendedVerifier.java | 58 +++++++++++++++++++---
+ src/test/gls/annotations/AnnotationTest.groovy     | 38 ++++++++++++++
+ 2 files changed, 89 insertions(+), 7 deletions(-)
+
+diff --git a/src/main/org/codehaus/groovy/classgen/ExtendedVerifier.java b/src/main/org/codehaus/groovy/classgen/ExtendedVerifier.java
+index bad5acc649..e1cb4182a1 100644
+--- a/src/main/org/codehaus/groovy/classgen/ExtendedVerifier.java
++++ b/src/main/org/codehaus/groovy/classgen/ExtendedVerifier.java
+@@ -19,7 +19,9 @@
+ package org.codehaus.groovy.classgen;
+ 
+ import org.codehaus.groovy.ast.*;
++import org.codehaus.groovy.ast.expr.ClassExpression;
+ import org.codehaus.groovy.ast.expr.DeclarationExpression;
++import org.codehaus.groovy.ast.expr.Expression;
+ import org.codehaus.groovy.ast.stmt.ReturnStatement;
+ import org.codehaus.groovy.ast.stmt.Statement;
+ import org.codehaus.groovy.ast.tools.ParameterUtils;
+@@ -34,6 +36,7 @@
+ import java.util.ArrayList;
+ import java.util.Arrays;
+ import java.util.HashMap;
++import java.util.LinkedHashMap;
+ import java.util.List;
+ import java.util.Map;
+ 
+@@ -135,21 +138,62 @@ protected void visitAnnotations(AnnotatedNode node, int target) {
+             addError("Annotations are not supported in the current runtime. " + JVM_ERROR_MESSAGE, node);
+             return;
+         }
++        Map<String, List<AnnotationNode>> runtimeAnnotations = new LinkedHashMap<String, List<AnnotationNode>>();
+         for (AnnotationNode unvisited : node.getAnnotations()) {
+             AnnotationNode visited = visitAnnotation(unvisited);
+-            boolean isTargetAnnotation = visited.getClassNode().isResolved() &&
+-                    visited.getClassNode().getName().equals("java.lang.annotation.Target");
++            String name = visited.getClassNode().getName();
++            if (visited.hasRuntimeRetention()) {
++                List<AnnotationNode> seen = runtimeAnnotations.get(name);
++                if (seen == null) {
++                    seen = new ArrayList<AnnotationNode>();
++                }
++                seen.add(visited);
++                runtimeAnnotations.put(name, seen);
++            }
++            boolean isTargetAnnotation = name.equals("java.lang.annotation.Target");
+ 
+             // Check if the annotation target is correct, unless it's the target annotating an annotation definition
+             // defining on which target elements the annotation applies
+             if (!isTargetAnnotation && !visited.isTargetAllowed(target)) {
+-                addError("Annotation @" + visited.getClassNode().getName()
+-                        + " is not allowed on element " + AnnotationNode.targetToName(target),
+-                        visited);
++                addError("Annotation @" + name + " is not allowed on element "
++                        + AnnotationNode.targetToName(target), visited);
+             }
+             visitDeprecation(node, visited);
+             visitOverride(node, visited);
+         }
++        checkForDuplicateAnnotations(runtimeAnnotations);
++    }
++
++    private void checkForDuplicateAnnotations(Map<String, List<AnnotationNode>> runtimeAnnotations) {
++        for (Map.Entry<String, List<AnnotationNode>> next : runtimeAnnotations.entrySet()) {
++            if (next.getValue().size() > 1) {
++                String repeatableName = null;
++                AnnotationNode repeatee = next.getValue().get(0);
++                List<AnnotationNode> repeateeAnnotations = repeatee.getClassNode().getAnnotations();
++                for (AnnotationNode anno : repeateeAnnotations) {
++                    ClassNode annoClassNode = anno.getClassNode();
++                    if (annoClassNode.getName().equals("java.lang.annotation.Repeatable")) {
++                        Expression value = anno.getMember("value");
++                        if (value instanceof ClassExpression) {
++                            ClassExpression ce = (ClassExpression) value;
++                            if (ce.getType() != null && ce.getType().isAnnotationDefinition()) {
++                                repeatableName = ce.getType().getName();
++                            }
++                        }
++                        break;
++                    }
++                }
++                // TODO: further checks: that repeatableName is valid and has RUNTIME retention?
++                if (repeatableName != null) {
++                    addError("Annotation @" + next.getKey() + " has RUNTIME retention and " + next.getValue().size()
++                            + " occurrences. Automatic repeated annotations are not supported in this version of Groovy. " +
++                            "Consider using the explicit @" + repeatableName + " collector annotation instead.", next.getValue().get(1));
++                } else {
++                    addError("Annotation @" + next.getKey() + " has RUNTIME retention and " + next.getValue().size()
++                            + " occurrences. Duplicate annotations not allowed.", next.getValue().get(1));
++                }
++            }
++        }
+     }
+ 
+     private static void visitDeprecation(AnnotatedNode node, AnnotationNode visited) {
+@@ -222,7 +266,7 @@ private static boolean isOverrideMethod(MethodNode method) {
+             }
+             ClassNode superClass = next.getUnresolvedSuperClass();
+             if (superClass != null) {
+-                next =  correctToGenericsSpecRecurse(updatedGenericsSpec, superClass);
++                next = correctToGenericsSpecRecurse(updatedGenericsSpec, superClass);
+             } else {
+                 next = null;
+             }
+@@ -231,7 +275,7 @@ private static boolean isOverrideMethod(MethodNode method) {
+     }
+ 
+     private static MethodNode getDeclaredMethodCorrected(Map genericsSpec, MethodNode mn, ClassNode correctedNext) {
+-        for (MethodNode orig :  correctedNext.getDeclaredMethods(mn.getName())) {
++        for (MethodNode orig : correctedNext.getDeclaredMethods(mn.getName())) {
+             MethodNode method = correctToGenericsSpec(genericsSpec, orig);
+             if (ParameterUtils.parametersEqual(method.getParameters(), mn.getParameters())) {
+                 return method;
+diff --git a/src/test/gls/annotations/AnnotationTest.groovy b/src/test/gls/annotations/AnnotationTest.groovy
+index 80e42427ac..9f306ff1e4 100644
+--- a/src/test/gls/annotations/AnnotationTest.groovy
++++ b/src/test/gls/annotations/AnnotationTest.groovy
+@@ -704,6 +704,44 @@ class AnnotationTest extends CompilableTestSupport {
+         '''
+     }
+ 
++    // GROOVY-8236
++    void testAnnotationWithRepeated() {
++        def errorMessage = shouldNotCompile '''
++            import java.lang.annotation.*
++
++            class MyClass {
++                @MyAnnotation(value = "val1")
++                @MyAnnotation(value = "val2")
++                //change annotation to next line and the code will work
++                //@MyAnnotationArray( [@MyAnnotation("val1"), @MyAnnotation("val2")] )
++                String annotatedMethod() {
++                    'foo'
++                }
++                static void main(String... args) {
++                    MyClass myc = new MyClass()
++                    assert 'foo' == myc.annotatedMethod()
++                    def m = myc.getClass().getMethod("annotatedMethod")
++                    List annos = m.getAnnotations()
++                    assert annos.size() == 1
++                }
++            }
++
++            @Target(ElementType.METHOD)
++            @Retention(RetentionPolicy.RUNTIME)
++            @Repeatable(MyAnnotationArray)
++            @interface MyAnnotation {
++                String value() default "val0"
++            }
++
++            @Retention(RetentionPolicy.RUNTIME)
++            @interface MyAnnotationArray {
++                MyAnnotation[] value()
++            }
++        '''
++        assert errorMessage.contains('Automatic repeated annotations are not supported')
++        assert errorMessage.contains('Consider using the explicit @MyAnnotationArray collector annotation')
++    }
++
+     //Parametrized tests in Spock would allow to make it much more readable
+     private static String codeWithMetaAnnotationWithTarget(String targetElementTypeName) {
+         """

http://git-wip-us.apache.org/repos/asf/groovy/blob/13522f88/pr584.patch
----------------------------------------------------------------------
diff --git a/pr584.patch b/pr584.patch
new file mode 100644
index 0000000..ec5c5fe
--- /dev/null
+++ b/pr584.patch
@@ -0,0 +1,57 @@
+From 2c11c1b72ff47e6c5ccb2134a7ea86da8cabc028 Mon Sep 17 00:00:00 2001
+From: John Wagenleitner <jw...@apache.org>
+Date: Sun, 13 Aug 2017 17:15:00 -0700
+Subject: [PATCH] GROOVY-8249: Newify local variable declaration fails to
+ resolve class expression
+
+---
+ .../groovy/classgen/VariableScopeVisitor.java      |  1 +
+ .../groovy/transform/NewifyTransformTest.groovy    | 24 ++++++++++++++++++++++
+ 2 files changed, 25 insertions(+)
+
+diff --git a/src/main/org/codehaus/groovy/classgen/VariableScopeVisitor.java b/src/main/org/codehaus/groovy/classgen/VariableScopeVisitor.java
+index 7a99014fed..f920211e32 100644
+--- a/src/main/org/codehaus/groovy/classgen/VariableScopeVisitor.java
++++ b/src/main/org/codehaus/groovy/classgen/VariableScopeVisitor.java
+@@ -330,6 +330,7 @@ public void visitIfElse(IfStatement ifElse) {
+     }
+ 
+     public void visitDeclarationExpression(DeclarationExpression expression) {
++        visitAnnotations(expression);
+         // visit right side first to avoid the usage of a
+         // variable before its declaration
+         expression.getRightExpression().visit(this);
+diff --git a/src/test/org/codehaus/groovy/transform/NewifyTransformTest.groovy b/src/test/org/codehaus/groovy/transform/NewifyTransformTest.groovy
+index d585c8a32c..c2cce48ef0 100644
+--- a/src/test/org/codehaus/groovy/transform/NewifyTransformTest.groovy
++++ b/src/test/org/codehaus/groovy/transform/NewifyTransformTest.groovy
+@@ -211,4 +211,28 @@ class NewifyTransformTest extends GroovyShellTestCase {
+             assert Foo.answer == 42
+         '''
+     }
++
++    // GROOVY-8249
++    void testLocalVariableDeclResolvesClass() {
++        assertScript '''
++            class A {
++                final int id
++                A(int id) { this.id = id + 10 }
++            }
++            class Foo {
++                static String test() {
++                    @Newify(String)
++                    String answer = String('bar')
++                    answer
++                }
++                static int test2() {
++                    @Newify(A)
++                    int answer = A(32).id
++                    answer
++                } 
++            }
++            assert Foo.test() == 'bar'
++            assert Foo.test2() == 42
++        '''
++    }
+ }
+\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/groovy/blob/13522f88/pr597.patch
----------------------------------------------------------------------
diff --git a/pr597.patch b/pr597.patch
new file mode 100644
index 0000000..3678787
--- /dev/null
+++ b/pr597.patch
@@ -0,0 +1,26 @@
+From 9740919cee991a573a45e288f8aa7d4490dfcc4f Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Aur=C3=A9lien=20Pupier?= <ap...@redhat.com>
+Date: Wed, 30 Aug 2017 17:39:44 +0200
+Subject: [PATCH] GROOVY-8305: Fix default Ivy settings file for local m2 path
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Aurélien Pupier <ap...@redhat.com>
+---
+ src/resources/groovy/grape/defaultGrapeConfig.xml | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/src/resources/groovy/grape/defaultGrapeConfig.xml b/src/resources/groovy/grape/defaultGrapeConfig.xml
+index 11161d37f4..a9f03062af 100644
+--- a/src/resources/groovy/grape/defaultGrapeConfig.xml
++++ b/src/resources/groovy/grape/defaultGrapeConfig.xml
+@@ -26,7 +26,7 @@
+         <ivy pattern="${user.home}/.groovy/grapes/[organisation]/[module]/ivy-[revision].xml"/>
+         <artifact pattern="${user.home}/.groovy/grapes/[organisation]/[module]/[type]s/[artifact]-[revision](-[classifier]).[ext]"/>
+       </filesystem>
+-      <ibiblio name="localm2" root="file:${user.home}/.m2/repository/" checkmodified="true" changingPattern=".*" changingMatcher="regexp" m2compatible="true"/>
++      <ibiblio name="localm2" root="file:/${user.home}/.m2/repository/" checkmodified="true" changingPattern=".*" changingMatcher="regexp" m2compatible="true"/>
+       <!-- todo add 'endorsed groovy extensions' resolver here -->
+       <ibiblio name="jcenter" root="https://jcenter.bintray.com/" m2compatible="true"/>
+       <ibiblio name="ibiblio" m2compatible="true"/>

http://git-wip-us.apache.org/repos/asf/groovy/blob/13522f88/pr603.patch
----------------------------------------------------------------------
diff --git a/pr603.patch b/pr603.patch
new file mode 100644
index 0000000..db060a1
--- /dev/null
+++ b/pr603.patch
@@ -0,0 +1,102 @@
+From e8fd90ae974fa97817682c1c4f8936feef2d2a66 Mon Sep 17 00:00:00 2001
+From: paulk <pa...@asert.com.au>
+Date: Mon, 18 Sep 2017 13:37:59 +1000
+Subject: [PATCH] GROOVY-8260: Static compilation requires casting inside
+ instanceof check
+
+---
+ .../transform/stc/StaticTypeCheckingVisitor.java   | 14 ++++--
+ src/test/groovy/bugs/Groovy8260Bug.groovy          | 57 ++++++++++++++++++++++
+ 2 files changed, 67 insertions(+), 4 deletions(-)
+ create mode 100644 src/test/groovy/bugs/Groovy8260Bug.groovy
+
+diff --git a/src/main/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java b/src/main/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
+index 12ea2b50f2..8c66eb7b9d 100644
+--- a/src/main/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
++++ b/src/main/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
+@@ -4018,12 +4018,18 @@ protected ClassNode getType(ASTNode exp) {
+             }
+             if (variable instanceof Parameter) {
+                 Parameter parameter = (Parameter) variable;
+-                ClassNode type = typeCheckingContext.controlStructureVariables.get(parameter);
++                ClassNode type = null;
++                // check if param part of control structure - but not if inside instanceof
++                List<ClassNode> temporaryTypesForExpression = getTemporaryTypesForExpression(vexp);
++                if (temporaryTypesForExpression == null || temporaryTypesForExpression.isEmpty()) {
++                    type = typeCheckingContext.controlStructureVariables.get(parameter);
++                }
++                // now check for closure override
+                 TypeCheckingContext.EnclosingClosure enclosingClosure = typeCheckingContext.getEnclosingClosure();
+-                ClassNode[] closureParamTypes = (ClassNode[])(enclosingClosure!=null?enclosingClosure.getClosureExpression().getNodeMetaData(StaticTypesMarker.CLOSURE_ARGUMENTS):null);
+-                if (type==null && enclosingClosure !=null && "it".equals(variable.getName()) && closureParamTypes!=null) {
++                ClassNode[] closureParamTypes = (ClassNode[]) (enclosingClosure != null ? enclosingClosure.getClosureExpression().getNodeMetaData(StaticTypesMarker.CLOSURE_ARGUMENTS) : null);
++                if (type == null && enclosingClosure != null && "it".equals(variable.getName()) && closureParamTypes != null) {
+                     final Parameter[] parameters = enclosingClosure.getClosureExpression().getParameters();
+-                    if (parameters.length==0 && getTemporaryTypesForExpression(vexp)==null && closureParamTypes.length!=0) {
++                    if (parameters.length == 0 && temporaryTypesForExpression == null && closureParamTypes.length != 0) {
+                         type = closureParamTypes[0];
+                     }
+                 }
+diff --git a/src/test/groovy/bugs/Groovy8260Bug.groovy b/src/test/groovy/bugs/Groovy8260Bug.groovy
+new file mode 100644
+index 0000000000..e69d68bdd3
+--- /dev/null
++++ b/src/test/groovy/bugs/Groovy8260Bug.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 groovy.bugs
++
++class Groovy8260Bug extends GroovyTestCase {
++
++    void testNoCastForInstanceofInsideLoop() {
++        assertScript '''
++            import groovy.transform.CompileStatic
++
++            interface FooI {
++                def intfMethod()
++            }
++
++            class Foo implements FooI {
++                def intfMethod() { 'Foo Interface method' }
++                def implMethod() { 'Foo Implementation method' }
++            }
++
++            @CompileStatic
++            def method(FooI propIn, List result) {
++                if (propIn instanceof Foo) {
++                    result << propIn.implMethod()
++                } else {
++                    result << propIn?.intfMethod()
++                }
++                for (FooI propLoop : [null, new Foo()]) {
++                    result << propLoop?.intfMethod()
++                    if (propLoop instanceof Foo) {
++                        result << propLoop.implMethod()
++                    }
++                }
++            }
++
++            def result = []
++            method(null, result)
++            assert result == [null, null, 'Foo Interface method', 'Foo Implementation method']
++        '''
++    }
++
++}

http://git-wip-us.apache.org/repos/asf/groovy/blob/13522f88/pr607.patch
----------------------------------------------------------------------
diff --git a/pr607.patch b/pr607.patch
new file mode 100644
index 0000000..8a5206b
--- /dev/null
+++ b/pr607.patch
@@ -0,0 +1,60 @@
+From f30d2e5dd6ce8045eb6656d1993f0dd9b07edfc5 Mon Sep 17 00:00:00 2001
+From: "alexey.afanasiev" <Al...@jetbrains.com>
+Date: Tue, 26 Sep 2017 17:43:15 +0300
+Subject: [PATCH] GROOVY-8330: Wrong 'Inconvertible types' error on casting
+ interface
+
+---
+ .../transform/stc/StaticTypeCheckingVisitor.java   |  2 ++
+ .../groovy/transform/stc/STCAssignmentTest.groovy  | 26 ++++++++++++++++++++++
+ 2 files changed, 28 insertions(+)
+
+diff --git a/src/main/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java b/src/main/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
+index cbb2798470..4c55eeafb8 100644
+--- a/src/main/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
++++ b/src/main/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
+@@ -3369,6 +3369,8 @@ protected boolean checkCast(final ClassNode targetType, final Expression source)
+             return false;
+         } else if ((expressionType.getModifiers()& Opcodes.ACC_FINAL)==0 && targetType.isInterface()) {
+             return true;
++        } else if ((targetType.getModifiers()& Opcodes.ACC_FINAL)==0 && expressionType.isInterface()) {
++            return true;
+         } else if (!isAssignableTo(targetType, expressionType) && !implementsInterfaceOrIsSubclassOf(expressionType, targetType)) {
+             return false;
+         }
+diff --git a/src/test/groovy/transform/stc/STCAssignmentTest.groovy b/src/test/groovy/transform/stc/STCAssignmentTest.groovy
+index 3c00185b90..acb1c7532b 100644
+--- a/src/test/groovy/transform/stc/STCAssignmentTest.groovy
++++ b/src/test/groovy/transform/stc/STCAssignmentTest.groovy
+@@ -872,5 +872,31 @@ class STCAssignmentTest extends StaticTypeCheckingTestCase {
+         }            
+         '''
+     }
++
++    void testNarrowingConversion() {
++        assertScript '''
++        interface A1{}
++        interface A2 extends A1{}
++        
++        class C1 implements A1{}
++        
++        def m(A2 a2) {
++            C1 c1 = (C1) a2
++        }
++        '''
++    }
++
++    void testFinalNarrowingConversion() {
++        shouldFailWithMessages '''
++        interface A1{}
++        interface A2 extends A1{}
++        
++        final class C1 implements A1{}
++        
++        def m(A2 a2) {
++            C1 c1 = (C1) a2
++        }
++        ''', "Inconvertible types: cannot cast A2 to C1"
++    }
+ }
+