This is an automated email from the ASF dual-hosted git repository.

sunlan pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/groovy.git


The following commit(s) were added to refs/heads/master by this push:
     new 6cb248a  GROOVY-9059: use redirect in generics spec if redirect is 
placeholder
6cb248a is described below

commit 6cb248a4716d3ed02ec1ea14a25adc776a8a68b6
Author: Eric Milles <[email protected]>
AuthorDate: Tue Aug 6 13:22:36 2019 -0500

    GROOVY-9059: use redirect in generics spec if redirect is placeholder
---
 .../codehaus/groovy/ast/tools/GenericsUtils.java   | 85 ++++++++++++----------
 .../codehaus/groovy/classgen/ExtendedVerifier.java | 68 +++++++----------
 .../org/codehaus/groovy/classgen/Verifier.java     |  8 +-
 src/test/groovy/bugs/Groovy9059.groovy             | 70 ++++++++++++++++++
 .../{Groovy6742Bug.groovy => Groovy6742.groovy}    | 60 ++++++++-------
 5 files changed, 180 insertions(+), 111 deletions(-)

diff --git a/src/main/java/org/codehaus/groovy/ast/tools/GenericsUtils.java 
b/src/main/java/org/codehaus/groovy/ast/tools/GenericsUtils.java
index b28771a..f9beb91 100644
--- a/src/main/java/org/codehaus/groovy/ast/tools/GenericsUtils.java
+++ b/src/main/java/org/codehaus/groovy/ast/tools/GenericsUtils.java
@@ -22,7 +22,6 @@ import antlr.RecognitionException;
 import antlr.TokenStreamException;
 import groovy.lang.Tuple2;
 import groovy.transform.stc.IncorrectTypeHintException;
-import org.apache.groovy.util.SystemUtil;
 import org.codehaus.groovy.GroovyBugError;
 import org.codehaus.groovy.antlr.AntlrParserPlugin;
 import org.codehaus.groovy.antlr.parser.GroovyLexer;
@@ -58,7 +57,7 @@ import java.util.concurrent.atomic.AtomicReference;
 import java.util.function.Predicate;
 
 import static groovy.lang.Tuple.tuple;
-import static org.codehaus.groovy.ast.GenericsType.GenericsTypeName;
+import static org.apache.groovy.util.SystemUtil.getSystemPropertySafe;
 import static 
org.codehaus.groovy.transform.stc.StaticTypeCheckingSupport.getCorrectedClassNode;
 import static 
org.codehaus.groovy.transform.stc.StaticTypeCheckingSupport.implementsInterfaceOrIsSubclassOf;
 
@@ -145,8 +144,8 @@ public class GenericsUtils {
         return gt;
     }
 
-    public static Map<GenericsTypeName, GenericsType> 
extractPlaceholders(ClassNode cn) {
-        Map<GenericsTypeName, GenericsType> ret = new 
HashMap<GenericsTypeName, GenericsType>();
+    public static Map<GenericsType.GenericsTypeName, GenericsType> 
extractPlaceholders(ClassNode cn) {
+        Map<GenericsType.GenericsTypeName, GenericsType> ret = new HashMap<>();
         extractPlaceholders(cn, ret);
         return ret;
     }
@@ -158,7 +157,7 @@ public class GenericsUtils {
      * @param node the class node to check
      * @param map the generics type information collector
      */
-    public static void extractPlaceholders(ClassNode node, 
Map<GenericsTypeName, GenericsType> map) {
+    public static void extractPlaceholders(ClassNode node, 
Map<GenericsType.GenericsTypeName, GenericsType> map) {
         if (node == null) return;
 
         if (node.isArray()) {
@@ -184,7 +183,7 @@ public class GenericsUtils {
         for (int i = 0; i < redirectGenericsTypes.length; i++) {
             GenericsType redirectType = redirectGenericsTypes[i];
             if (redirectType.isPlaceholder()) {
-                GenericsTypeName name = new 
GenericsTypeName(redirectType.getName());
+                GenericsType.GenericsTypeName name = new 
GenericsType.GenericsTypeName(redirectType.getName());
                 if (!map.containsKey(name)) {
                     GenericsType value = parameterized[i];
                     map.put(name, value);
@@ -316,7 +315,7 @@ public class GenericsUtils {
         if (type.isArray()) {
             return makeClassSafeWithGenerics(type.getComponentType(), 
genericTypes).makeArray();
         }
-        GenericsType[] gtypes = GenericsType.EMPTY_ARRAY;
+        GenericsType[] gtypes = EMPTY_GENERICS_ARRAY;
         if (genericTypes != null) {
             gtypes = new GenericsType[genericTypes.length];
             System.arraycopy(genericTypes, 0, gtypes, 0, gtypes.length);
@@ -325,6 +324,7 @@ public class GenericsUtils {
     }
 
     public static MethodNode correctToGenericsSpec(Map<String, ClassNode> 
genericsSpec, MethodNode mn) {
+        if (mn.getGenericsTypes() != null) genericsSpec = 
addMethodGenerics(mn, genericsSpec);
         ClassNode correctedType = correctToGenericsSpecRecurse(genericsSpec, 
mn.getReturnType());
         Parameter[] origParameters = mn.getParameters();
         Parameter[] newParameters = new Parameter[origParameters.length];
@@ -361,15 +361,19 @@ public class GenericsUtils {
         if (type.isGenericsPlaceHolder() && 
!exclusions.contains(type.getUnresolvedName())) {
             String name = type.getGenericsTypes()[0].getName();
             type = genericsSpec.get(name);
-            if (type != null && type.isGenericsPlaceHolder() && 
type.getGenericsTypes() == null) {
-                ClassNode placeholder = 
ClassHelper.makeWithoutCaching(type.getUnresolvedName());
-                placeholder.setGenericsPlaceHolder(true);
-                type = makeClassSafeWithGenerics(type, new 
GenericsType(placeholder));
+            if (type != null && type.isGenericsPlaceHolder()) {
+                if (type.getGenericsTypes() == null) {
+                    ClassNode placeholder = 
ClassHelper.makeWithoutCaching(type.getUnresolvedName());
+                    placeholder.setGenericsPlaceHolder(true);
+                    return makeClassSafeWithGenerics(type, new 
GenericsType(placeholder));
+                } else if (!name.equals(type.getUnresolvedName())) {
+                    return correctToGenericsSpecRecurse(genericsSpec, type, 
exclusions);
+                }
             }
         }
         if (type == null) type = ClassHelper.OBJECT_TYPE;
         GenericsType[] oldgTypes = type.getGenericsTypes();
-        GenericsType[] newgTypes = GenericsType.EMPTY_ARRAY;
+        GenericsType[] newgTypes = EMPTY_GENERICS_ARRAY;
         if (oldgTypes != null) {
             newgTypes = new GenericsType[oldgTypes.length];
             for (int i = 0; i < newgTypes.length; i++) {
@@ -417,17 +421,20 @@ public class GenericsUtils {
         if (type.isArray()) {
             return correctToGenericsSpec(genericsSpec, 
type.getComponentType()).makeArray();
         }
-        if (type.isGenericsPlaceHolder()) {
+        if (type.isGenericsPlaceHolder() && type.getGenericsTypes() != null) {
             String name = type.getGenericsTypes()[0].getName();
             type = genericsSpec.get(name);
+            if (type != null && type.isGenericsPlaceHolder()
+                    && !name.equals(type.getUnresolvedName())) {
+                return correctToGenericsSpec(genericsSpec, type);
+            }
         }
         if (type == null) type = ClassHelper.OBJECT_TYPE;
         return type;
     }
 
-    @SuppressWarnings("unchecked")
     public static Map<String, ClassNode> createGenericsSpec(ClassNode current) 
{
-        return createGenericsSpec(current, Collections.EMPTY_MAP);
+        return createGenericsSpec(current, Collections.emptyMap());
     }
 
     public static Map<String, ClassNode> createGenericsSpec(ClassNode current, 
Map<String, ClassNode> oldSpec) {
@@ -459,28 +466,31 @@ public class GenericsUtils {
     }
 
     public static Map<String, ClassNode> addMethodGenerics(MethodNode current, 
Map<String, ClassNode> oldSpec) {
-        Map<String, ClassNode> ret = new HashMap<String, ClassNode>(oldSpec);
+        Map<String, ClassNode> ret = new HashMap<>(oldSpec);
         // ret starts with the original type specs, now add gts for the 
current method if any
-        GenericsType[] sgts = current.getGenericsTypes();
-        if (sgts != null) {
-            for (GenericsType sgt : sgts) {
-                String name = sgt.getName();
-                if (sgt.isPlaceholder()) {
+        GenericsType[] gts = current.getGenericsTypes();
+        if (gts != null) {
+            for (GenericsType gt : gts) {
+                String name = gt.getName();
+                ClassNode type = gt.getType();
+                if (gt.isPlaceholder()) {
                     ClassNode redirect;
-                    if (sgt.getUpperBounds() != null) {
-                        redirect = sgt.getUpperBounds()[0];
-                    } else if (sgt.getLowerBound() != null) {
-                        redirect = sgt.getLowerBound();
+                    if (gt.getUpperBounds() != null) {
+                        redirect = gt.getUpperBounds()[0];
+                    } else if (gt.getLowerBound() != null) {
+                        redirect = gt.getLowerBound();
                     } else {
                         redirect = ClassHelper.OBJECT_TYPE;
                     }
-                    ClassNode type = ClassHelper.makeWithoutCaching(name);
-                    type.setGenericsPlaceHolder(true);
-                    type.setRedirect(redirect);
-                    ret.put(name, type);
-                } else {
-                    ret.put(name, sgt.getType());
+                    if (redirect.isGenericsPlaceHolder()) {
+                        type = redirect;
+                    } else {
+                        type = ClassHelper.makeWithoutCaching(name);
+                        type.setGenericsPlaceHolder(true);
+                        type.setRedirect(redirect);
+                    }
                 }
+                ret.put(name, type);
             }
         }
         return ret;
@@ -509,7 +519,7 @@ public class GenericsUtils {
                 ClassNode corrected = getCorrectedClassNode(type, superClass, 
false);
                 extractSuperClassGenerics(corrected, target, spec);
             } else {
-                // if we reach here, we have an unhandled case 
+                // if we reach here, we have an unhandled case
                 throw new GroovyBugError("The type " + type + " seems not to 
normally extend " + target + ". Sorry, I cannot handle this.");
             }
         }
@@ -528,7 +538,7 @@ public class GenericsUtils {
     }
 
     private static void extractSuperClassGenerics(GenericsType[] usage, 
GenericsType[] declaration, Map<String, ClassNode> spec) {
-        // if declaration does not provide generics, there is no connection to 
make 
+        // if declaration does not provide generics, there is no connection to 
make
         if (usage == null || declaration == null || declaration.length == 0) 
return;
         if (usage.length != declaration.length) return;
 
@@ -634,8 +644,9 @@ public class GenericsUtils {
     }
 
     /**
-     * transforms generics types from an old context to a new context using 
the given spec. This method assumes
-     * all generics types will be placeholders. WARNING: The resulting 
generics types may or may not be placeholders
+     * Transforms generics types from an old context to a new context using the
+     * given spec. This method assumes all generics types will be placeholders.
+     * WARNING: The resulting generics types may or may not be placeholders
      * after the transformation.
      *
      * @param genericsSpec    the generics context information spec
@@ -683,9 +694,7 @@ public class GenericsUtils {
         return newTypes;
     }
 
-    private static final String TRUE_STR = "true";
-    private static final boolean PARAMETERIZED_TYPE_CACHE_ENABLED =
-            
TRUE_STR.equals(SystemUtil.getSystemPropertySafe("groovy.enable.parameterized.type.cache",
 TRUE_STR));
+    private static final boolean PARAMETERIZED_TYPE_CACHE_ENABLED = 
Boolean.parseBoolean(getSystemPropertySafe("groovy.enable.parameterized.type.cache",
 "true"));
 
     /**
      * Try to get the parameterized type from the cache.
diff --git a/src/main/java/org/codehaus/groovy/classgen/ExtendedVerifier.java 
b/src/main/java/org/codehaus/groovy/classgen/ExtendedVerifier.java
index 58a5bc3..16a1591 100644
--- a/src/main/java/org/codehaus/groovy/classgen/ExtendedVerifier.java
+++ b/src/main/java/org/codehaus/groovy/classgen/ExtendedVerifier.java
@@ -18,7 +18,6 @@
  */
 package org.codehaus.groovy.classgen;
 
-import org.codehaus.groovy.ast.ASTNode;
 import org.codehaus.groovy.ast.AnnotatedNode;
 import org.codehaus.groovy.ast.AnnotationNode;
 import org.codehaus.groovy.ast.ClassCodeVisitorSupport;
@@ -26,7 +25,6 @@ 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.GenericsType;
 import org.codehaus.groovy.ast.MethodNode;
 import org.codehaus.groovy.ast.PackageNode;
 import org.codehaus.groovy.ast.Parameter;
@@ -43,15 +41,13 @@ import 
org.codehaus.groovy.control.AnnotationConstantsVisitor;
 import org.codehaus.groovy.control.CompilerConfiguration;
 import org.codehaus.groovy.control.ErrorCollector;
 import org.codehaus.groovy.control.SourceUnit;
-import org.codehaus.groovy.control.messages.SyntaxErrorMessage;
-import org.codehaus.groovy.syntax.SyntaxException;
 import org.objectweb.asm.Opcodes;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.HashMap;
+import java.util.Collections;
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
@@ -77,6 +73,12 @@ public class ExtendedVerifier extends 
ClassCodeVisitorSupport {
         this.source = sourceUnit;
     }
 
+    @Override
+    protected SourceUnit getSourceUnit() {
+        return this.source;
+    }
+
+    @Override
     public void visitClass(ClassNode node) {
         AnnotationConstantsVisitor acv = new AnnotationConstantsVisitor();
         acv.visitClass(node, this.source);
@@ -93,6 +95,7 @@ public class ExtendedVerifier extends ClassCodeVisitorSupport 
{
         node.visitContents(this);
     }
 
+    @Override
     public void visitField(FieldNode node) {
         visitAnnotations(node, AnnotationNode.FIELD_TARGET);
     }
@@ -102,25 +105,26 @@ public class ExtendedVerifier extends 
ClassCodeVisitorSupport {
         visitAnnotations(expression, AnnotationNode.LOCAL_VARIABLE_TARGET);
     }
 
+    @Override
     public void visitConstructor(ConstructorNode node) {
         visitConstructorOrMethod(node, AnnotationNode.CONSTRUCTOR_TARGET);
     }
 
+    @Override
     public void visitMethod(MethodNode node) {
         visitConstructorOrMethod(node, AnnotationNode.METHOD_TARGET);
     }
 
     private void visitConstructorOrMethod(MethodNode node, int methodTarget) {
         visitAnnotations(node, methodTarget);
-        for (int i = 0; i < node.getParameters().length; i++) {
-            Parameter parameter = node.getParameters()[i];
+        for (Parameter parameter : node.getParameters()) {
             visitAnnotations(parameter, AnnotationNode.PARAMETER_TARGET);
         }
 
         if (this.currentClass.isAnnotationDefinition() && 
!node.isStaticConstructor()) {
             ErrorCollector errorCollector = new 
ErrorCollector(this.source.getConfiguration());
             AnnotationVisitor visitor = new AnnotationVisitor(this.source, 
errorCollector);
-            visitor.setReportClass(currentClass);
+            visitor.setReportClass(this.currentClass);
             visitor.checkReturnType(node.getReturnType(), node);
             if (node.getParameters().length > 0) {
                 addError("Annotation members may not have parameters.", 
node.getParameters()[0]);
@@ -131,7 +135,7 @@ public class ExtendedVerifier extends 
ClassCodeVisitorSupport {
             ReturnStatement code = (ReturnStatement) node.getCode();
             if (code != null) {
                 visitor.visitExpression(node.getName(), code.getExpression(), 
node.getReturnType());
-                visitor.checkCircularReference(currentClass, 
node.getReturnType(), code.getExpression());
+                visitor.checkCircularReference(this.currentClass, 
node.getReturnType(), code.getExpression());
             }
             
this.source.getErrorCollector().addCollectorContents(errorCollector);
         }
@@ -139,9 +143,9 @@ public class ExtendedVerifier extends 
ClassCodeVisitorSupport {
         if (code != null) {
             code.visit(this);
         }
-
     }
 
+    @Override
     public void visitProperty(PropertyNode node) {
     }
 
@@ -180,8 +184,8 @@ public class ExtendedVerifier extends 
ClassCodeVisitorSupport {
         checkForDuplicateAnnotations(node, nonSourceAnnotations);
     }
 
-    private void checkForDuplicateAnnotations(AnnotatedNode node, Map<String, 
List<AnnotationNode>> runtimeAnnotations) {
-        for (Map.Entry<String, List<AnnotationNode>> next : 
runtimeAnnotations.entrySet()) {
+    private void checkForDuplicateAnnotations(AnnotatedNode node, Map<String, 
List<AnnotationNode>> nonSourceAnnotations) {
+        for (Map.Entry<String, List<AnnotationNode>> next : 
nonSourceAnnotations.entrySet()) {
             if (next.getValue().size() > 1) {
                 ClassNode repeatable = null;
                 AnnotationNode repeatee = next.getValue().get(0);
@@ -275,7 +279,7 @@ public class ExtendedVerifier extends 
ClassCodeVisitorSupport {
         ClassNode next = cNode;
         outer:
         while (next != null) {
-            Map genericsSpec = createGenericsSpec(next);
+            Map<String, ClassNode> genericsSpec = createGenericsSpec(next);
             MethodNode mn = correctToGenericsSpec(genericsSpec, method);
             if (next != cNode) {
                 ClassNode correctedNext = 
correctToGenericsSpecRecurse(genericsSpec, next);
@@ -283,20 +287,19 @@ public class ExtendedVerifier extends 
ClassCodeVisitorSupport {
                 if (found != null) break;
             }
             List<ClassNode> ifaces = new 
ArrayList<ClassNode>(Arrays.asList(next.getInterfaces()));
-            Map updatedGenericsSpec = new HashMap(genericsSpec);
             while (!ifaces.isEmpty()) {
                 ClassNode origInterface = ifaces.remove(0);
                 if (!origInterface.equals(ClassHelper.OBJECT_TYPE)) {
-                    updatedGenericsSpec = createGenericsSpec(origInterface, 
updatedGenericsSpec);
-                    ClassNode iNode = 
correctToGenericsSpecRecurse(updatedGenericsSpec, origInterface);
-                    MethodNode found2 = 
getDeclaredMethodCorrected(updatedGenericsSpec, mn, iNode);
+                    genericsSpec = createGenericsSpec(origInterface, 
genericsSpec);
+                    ClassNode iNode = 
correctToGenericsSpecRecurse(genericsSpec, origInterface);
+                    MethodNode found2 = 
getDeclaredMethodCorrected(genericsSpec, mn, iNode);
                     if (found2 != null) break outer;
-                    ifaces.addAll(Arrays.asList(iNode.getInterfaces()));
+                    Collections.addAll(ifaces, iNode.getInterfaces());
                 }
             }
             ClassNode superClass = next.getUnresolvedSuperClass();
             if (superClass != null) {
-                next = correctToGenericsSpecRecurse(updatedGenericsSpec, 
superClass);
+                next = correctToGenericsSpecRecurse(genericsSpec, superClass);
             } else {
                 next = null;
             }
@@ -305,10 +308,10 @@ public class ExtendedVerifier extends 
ClassCodeVisitorSupport {
     }
 
     private static MethodNode getDeclaredMethodCorrected(Map genericsSpec, 
MethodNode mn, ClassNode correctedNext) {
-        for (MethodNode orig : correctedNext.getDeclaredMethods(mn.getName())) 
{
-            MethodNode method = correctToGenericsSpec(genericsSpec, orig);
-            if (ParameterUtils.parametersEqual(method.getParameters(), 
mn.getParameters())) {
-                return method;
+        for (MethodNode declared : 
correctedNext.getDeclaredMethods(mn.getName())) {
+            MethodNode corrected = correctToGenericsSpec(genericsSpec, 
declared);
+            if (ParameterUtils.parametersEqual(corrected.getParameters(), 
mn.getParameters())) {
+                return corrected;
             }
         }
         return null;
@@ -336,21 +339,4 @@ public class ExtendedVerifier extends 
ClassCodeVisitorSupport {
     protected boolean isAnnotationCompatible() {
         return 
CompilerConfiguration.isPostJDK5(this.source.getConfiguration().getTargetBytecode());
     }
-
-    public void addError(String msg, ASTNode expr) {
-        this.source.getErrorCollector().addErrorAndContinue(
-                new SyntaxErrorMessage(
-                        new SyntaxException(msg + '\n', expr.getLineNumber(), 
expr.getColumnNumber(), expr.getLastLineNumber(), expr.getLastColumnNumber()), 
this.source)
-        );
-    }
-
-    @Override
-    protected SourceUnit getSourceUnit() {
-        return source;
-    }
-
-    // TODO use it or lose it
-    public void visitGenericType(GenericsType genericsType) {
-
-    }
-}
\ No newline at end of file
+}
diff --git a/src/main/java/org/codehaus/groovy/classgen/Verifier.java 
b/src/main/java/org/codehaus/groovy/classgen/Verifier.java
index d821a3f..2230085 100644
--- a/src/main/java/org/codehaus/groovy/classgen/Verifier.java
+++ b/src/main/java/org/codehaus/groovy/classgen/Verifier.java
@@ -1330,7 +1330,7 @@ public class Verifier implements GroovyClassVisitor, 
Opcodes {
         return null;
     }
 
-    public static long getTimestamp(Class clazz) {
+    public static long getTimestamp(Class<?> clazz) {
         if (clazz.getClassLoader() instanceof GroovyClassLoader.InnerLoader) {
             GroovyClassLoader.InnerLoader innerLoader = 
(GroovyClassLoader.InnerLoader) clazz.getClassLoader();
             return innerLoader.getTimeStamp();
@@ -1438,14 +1438,14 @@ public class Verifier implements GroovyClassVisitor, 
Opcodes {
         if ((overridingMethod.getModifiers() & ACC_BRIDGE) != 0) return null;
         if (oldMethod.isPrivate()) return null;
 
+        if (oldMethod.getGenericsTypes() != null)
+            genericsSpec = addMethodGenerics(oldMethod, genericsSpec);
+
         // parameters
         boolean normalEqualParameters = 
equalParametersNormal(overridingMethod, oldMethod);
         boolean genericEqualParameters = 
equalParametersWithGenerics(overridingMethod, oldMethod, genericsSpec);
         if (!normalEqualParameters && !genericEqualParameters) return null;
 
-        //correct to method level generics for the overriding method
-        genericsSpec = addMethodGenerics(overridingMethod, genericsSpec);
-
         // return type
         ClassNode mr = overridingMethod.getReturnType();
         ClassNode omr = oldMethod.getReturnType();
diff --git a/src/test/groovy/bugs/Groovy9059.groovy 
b/src/test/groovy/bugs/Groovy9059.groovy
new file mode 100644
index 0000000..71f17eb
--- /dev/null
+++ b/src/test/groovy/bugs/Groovy9059.groovy
@@ -0,0 +1,70 @@
+/*
+ * 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
+
+import groovy.transform.CompileStatic
+import org.junit.Test
+
+import static groovy.test.GroovyAssert.assertScript
+
+@CompileStatic
+final class Groovy9059 {
+
+    @Test
+    void testTypeParameterWithExtends1() {
+        assertScript '''
+            interface Face<T> {
+                public <O extends T> O process(O o)
+            }
+
+            def impl = new Face<CharSequence>() {
+                @Override
+                public <Chars extends CharSequence> Chars process(Chars chars) 
{ chars }
+            }
+        '''
+    }
+
+    @Test
+    void testTypeParameterWithExtends2() {
+        assertScript '''
+            interface Face<T> {
+                public <O extends T> O process(O o)
+            }
+
+            def impl = new Face<CharSequence>() {
+                @Override @SuppressWarnings('unchecked')
+                public CharSequence process(CharSequence chars) { chars }
+            }
+        '''
+    }
+
+    @Test
+    void testTypeParameterWithExtends3() {
+        assertScript '''
+            interface Face<T> {
+                public <O extends T> O process(O o)
+            }
+
+            def impl = new Face<String>() {
+                @Override @SuppressWarnings('unchecked')
+                public String process(String string) { string }
+            }
+        '''
+    }
+}
diff --git a/src/test/groovy/bugs/groovy6742/Groovy6742Bug.groovy 
b/src/test/groovy/bugs/groovy6742/Groovy6742.groovy
similarity index 65%
rename from src/test/groovy/bugs/groovy6742/Groovy6742Bug.groovy
rename to src/test/groovy/bugs/groovy6742/Groovy6742.groovy
index fcc953a..1e4169b 100644
--- a/src/test/groovy/bugs/groovy6742/Groovy6742Bug.groovy
+++ b/src/test/groovy/bugs/groovy6742/Groovy6742.groovy
@@ -1,32 +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
+ * 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
+ *     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.
+ * 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.groovy6742
 
+import groovy.transform.CompileStatic
+import org.junit.Test
 
+import static groovy.test.GroovyAssert.assertScript
 
+@CompileStatic
+final class Groovy6742 {
 
-package groovy.bugs.groovy6742
-
-class Groovy6742Bug extends GroovyTestCase {
+    @Test
     void test1() {
         assertScript '''
             package groovy.bugs.groovy6742
-            
+
             @groovy.transform.TypeChecked
             class Issue1 {
                 public void issue(){
@@ -38,15 +42,16 @@ class Groovy6742Bug extends GroovyTestCase {
                     }
                 }
             }
-            
+
             assert true
         '''
     }
 
+    @Test
     void test2() {
         assertScript '''
             package groovy.bugs.groovy6742
-            
+
             @groovy.transform.TypeChecked
             class Issue2 {
                 public void issue() {
@@ -57,37 +62,36 @@ class Groovy6742Bug extends GroovyTestCase {
                         }
                     })
                 }
-            
+
                 public <I, O> void transform(Function<? super I, ? extends O> 
function) {
-            
                 }
             }
-            
+
             assert true
         '''
     }
 
+    @Test
     void test3() {
         assertScript '''
             package groovy.bugs.groovy6742
-            
+
             @groovy.transform.TypeChecked
             class Issue3 {
                 public static <F, T> FutureCallback<F> 
deferredCallback(DeferredResult<T> deferredResult, final Function<F, T> 
function) {
                     return new FutureCallback<F>() {
                         private F f = null
                         F f2 = null
-                        
+
                         @Override
                         void onSuccess(F result) {
                             deferredResult.setResult(function.apply(result))
                         }
-                    };
+                    }
                 }
             }
-            
+
             assert true
         '''
     }
-
 }

Reply via email to